OR-Tools  8.1
file.cc
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 
17 #include "absl/strings/str_cat.h"
18 #if defined(_MSC_VER)
19 #include <io.h>
20 #define access _access
21 #define F_OK 0
22 #else
23 #include <unistd.h>
24 #endif
25 
26 #include <cstring>
27 #include <memory>
28 #include <string>
29 
30 #include "ortools/base/file.h"
31 #include "ortools/base/logging.h"
32 
33 File::File(FILE* const f_des, const absl::string_view& name)
34  : f_(f_des), name_(name) {}
35 
36 bool File::Delete(const char* const name) { return remove(name) == 0; }
37 
38 bool File::Exists(const char* const name) { return access(name, F_OK) == 0; }
39 
40 size_t File::Size() {
41  struct stat f_stat;
42  stat(name_.data(), &f_stat);
43  return f_stat.st_size;
44 }
45 
46 bool File::Flush() { return fflush(f_) == 0; }
47 
48 bool File::Close() {
49  if (fclose(f_) == 0) {
50  f_ = NULL;
51  return true;
52  } else {
53  return false;
54  }
55 }
56 
57 absl::Status File::Close(int flags) {
58  if (flags != file::Defaults())
59  return absl::Status(absl::StatusCode::kInvalidArgument, "Wrong flags");
60  return Close()
61  ? absl::OkStatus()
62  : absl::Status(absl::StatusCode::kInvalidArgument,
63  absl::StrCat("Could not close file '", name_, "'"));
64 }
65 
66 void File::ReadOrDie(void* const buf, size_t size) {
67  CHECK_EQ(fread(buf, 1, size, f_), size);
68 }
69 
70 size_t File::Read(void* const buf, size_t size) {
71  return fread(buf, 1, size, f_);
72 }
73 
74 void File::WriteOrDie(const void* const buf, size_t size) {
75  CHECK_EQ(fwrite(buf, 1, size, f_), size);
76 }
77 size_t File::Write(const void* const buf, size_t size) {
78  return fwrite(buf, 1, size, f_);
79 }
80 
81 File* File::OpenOrDie(const char* const name, const char* const flag) {
82  FILE* const f_des = fopen(name, flag);
83  if (f_des == NULL) {
84  std::cerr << "Cannot open " << name;
85  exit(1);
86  }
87  File* const f = new File(f_des, name);
88  return f;
89 }
90 
91 File* File::Open(const char* const name, const char* const flag) {
92  FILE* const f_des = fopen(name, flag);
93  if (f_des == NULL) return NULL;
94  File* const f = new File(f_des, name);
95  return f;
96 }
97 
98 char* File::ReadLine(char* const output, uint64 max_length) {
99  return fgets(output, max_length, f_);
100 }
101 
102 int64 File::ReadToString(std::string* const output, uint64 max_length) {
103  CHECK(output != nullptr);
104  output->clear();
105 
106  if (max_length == 0) return 0;
107 
108  int64 needed = max_length;
109  int bufsize = (needed < (2 << 20) ? needed : (2 << 20));
110 
111  std::unique_ptr<char[]> buf(new char[bufsize]);
112 
113  int64 nread = 0;
114  while (needed > 0) {
115  nread = Read(buf.get(), (bufsize < needed ? bufsize : needed));
116  if (nread > 0) {
117  output->append(buf.get(), nread);
118  needed -= nread;
119  } else {
120  break;
121  }
122  }
123  return (nread >= 0 ? static_cast<int64>(output->size()) : -1);
124 }
125 
126 size_t File::WriteString(const std::string& line) {
127  return Write(line.c_str(), line.size());
128 }
129 
130 bool File::WriteLine(const std::string& line) {
131  if (Write(line.c_str(), line.size()) != line.size()) return false;
132  return Write("\n", 1) == 1;
133 }
134 
135 absl::string_view File::filename() const { return name_; }
136 
137 bool File::Open() const { return f_ != NULL; }
138 
139 void File::Init() {}
140 
141 namespace file {
142 absl::Status Open(const absl::string_view& filename,
143  const absl::string_view& mode, File** f, int flags) {
144  if (flags == Defaults()) {
145  *f = File::Open(filename, mode.data());
146  if (*f != nullptr) {
147  return absl::OkStatus();
148  }
149  }
150  return absl::Status(absl::StatusCode::kInvalidArgument,
151  absl::StrCat("Could not open '", filename, "'"));
152 }
153 
154 File* OpenOrDie(const absl::string_view& filename,
155  const absl::string_view& mode, int flags) {
156  File* f;
157  CHECK_EQ(flags, Defaults());
158  f = File::Open(filename, mode.data());
159  CHECK(f != nullptr) << absl::StrCat("Could not open '", filename, "'");
160  return f;
161 }
162 
163 absl::Status GetContents(const absl::string_view& filename, std::string* output,
164  int flags) {
165  if (flags == Defaults()) {
166  File* file = File::Open(filename, "r");
167  if (file != NULL) {
168  const int64 size = file->Size();
169  if (file->ReadToString(output, size) == size) return absl::OkStatus();
170  }
171  }
172  return absl::Status(absl::StatusCode::kInvalidArgument,
173  absl::StrCat("Could not read '", filename, "'"));
174 }
175 
176 absl::Status WriteString(File* file, const absl::string_view& contents,
177  int flags) {
178  if (flags == Defaults() && file != NULL &&
179  file->Write(contents.data(), contents.size()) == contents.size() &&
180  file->Close()) {
181  return absl::OkStatus();
182  }
183  return absl::Status(
184  absl::StatusCode::kInvalidArgument,
185  absl::StrCat("Could not write ", contents.size(), " bytes"));
186 }
187 
188 absl::Status SetContents(const absl::string_view& filename,
189  const absl::string_view& contents, int flags) {
190  return WriteString(File::Open(filename, "w"), contents, flags);
191 }
192 
193 bool ReadFileToString(const absl::string_view& file_name, std::string* output) {
194  return GetContents(file_name, output, file::Defaults()).ok();
195 }
196 
197 bool WriteStringToFile(const std::string& data,
198  const absl::string_view& file_name) {
199  return SetContents(file_name, data, file::Defaults()).ok();
200 }
201 
202 namespace {
203 class NoOpErrorCollector : public google::protobuf::io::ErrorCollector {
204  public:
205  virtual void AddError(int line, int column, const std::string& message) {}
206 };
207 } // namespace
208 
209 bool ReadFileToProto(const absl::string_view& file_name,
210  google::protobuf::Message* proto) {
211  std::string str;
212  if (!ReadFileToString(file_name, &str)) {
213  LOG(INFO) << "Could not read " << file_name;
214  return false;
215  }
216  // Attempt to decode ASCII before deciding binary. Do it in this order because
217  // it is much harder for a binary encoding to happen to be a valid ASCII
218  // encoding than the other way around. For instance "index: 1\n" is a valid
219  // (but nonsensical) binary encoding. We want to avoid printing errors for
220  // valid binary encodings if the ASCII parsing fails, and so specify a no-op
221  // error collector.
222  NoOpErrorCollector error_collector;
223  google::protobuf::TextFormat::Parser parser;
224  parser.RecordErrorsTo(&error_collector);
225  if (parser.ParseFromString(str, proto)) {
226  return true;
227  }
228  if (proto->ParseFromString(str)) {
229  return true;
230  }
231  // Re-parse the ASCII, just to show the diagnostics (we could also get them
232  // out of the ErrorCollector but this way is easier).
233  google::protobuf::TextFormat::ParseFromString(str, proto);
234  LOG(INFO) << "Could not parse contents of " << file_name;
235  return false;
236 }
237 
238 void ReadFileToProtoOrDie(const absl::string_view& file_name,
239  google::protobuf::Message* proto) {
240  CHECK(ReadFileToProto(file_name, proto)) << "file_name: " << file_name;
241 }
242 
243 bool WriteProtoToASCIIFile(const google::protobuf::Message& proto,
244  const absl::string_view& file_name) {
245  std::string proto_string;
246  return google::protobuf::TextFormat::PrintToString(proto, &proto_string) &&
247  WriteStringToFile(proto_string, file_name);
248 }
249 
250 void WriteProtoToASCIIFileOrDie(const google::protobuf::Message& proto,
251  const absl::string_view& file_name) {
252  CHECK(WriteProtoToASCIIFile(proto, file_name)) << "file_name: " << file_name;
253 }
254 
255 bool WriteProtoToFile(const google::protobuf::Message& proto,
256  const absl::string_view& file_name) {
257  std::string proto_string;
258  return proto.AppendToString(&proto_string) &&
259  WriteStringToFile(proto_string, file_name);
260 }
261 
262 void WriteProtoToFileOrDie(const google::protobuf::Message& proto,
263  const absl::string_view& file_name) {
264  CHECK(WriteProtoToFile(proto, file_name)) << "file_name: " << file_name;
265 }
266 
267 absl::Status GetTextProto(const absl::string_view& filename,
268  google::protobuf::Message* proto, int flags) {
269  if (flags == Defaults()) {
270  if (ReadFileToProto(filename, proto)) return absl::OkStatus();
271  }
272  return absl::Status(
273  absl::StatusCode::kInvalidArgument,
274  absl::StrCat("Could not read proto from '", filename, "'."));
275 }
276 
277 absl::Status SetTextProto(const absl::string_view& filename,
278  const google::protobuf::Message& proto, int flags) {
279  if (flags == Defaults()) {
280  if (WriteProtoToASCIIFile(proto, filename)) return absl::OkStatus();
281  }
282  return absl::Status(
283  absl::StatusCode::kInvalidArgument,
284  absl::StrCat("Could not write proto to '", filename, "'."));
285 }
286 
287 absl::Status SetBinaryProto(const absl::string_view& filename,
288  const google::protobuf::Message& proto, int flags) {
289  if (flags == Defaults()) {
290  if (WriteProtoToFile(proto, filename)) return absl::OkStatus();
291  }
292  return absl::Status(
293  absl::StatusCode::kInvalidArgument,
294  absl::StrCat("Could not write proto to '", filename, "'."));
295 }
296 
297 absl::Status Delete(const absl::string_view& path, int flags) {
298  if (flags == Defaults()) {
299  if (remove(path.data()) == 0) return absl::OkStatus();
300  }
301  return absl::Status(absl::StatusCode::kInvalidArgument,
302  absl::StrCat("Could not delete '", path, "'."));
303 }
304 
305 absl::Status Exists(const absl::string_view& path, int flags) {
306  if (flags == Defaults()) {
307  if (access(path.data(), F_OK) == 0) return absl::OkStatus();
308  }
309  return absl::Status(absl::StatusCode::kInvalidArgument,
310  absl::StrCat("File '", path, "' does not exist."));
311 }
312 } // namespace file
operations_research::ReadFileToString
absl::StatusOr< std::string > ReadFileToString(absl::string_view filename)
Definition: file_util.cc:30
file::SetContents
absl::Status SetContents(const absl::string_view &filename, const absl::string_view &contents, int flags)
Definition: file.cc:188
INFO
const int INFO
Definition: log_severity.h:31
File::Init
static void Init()
Definition: file.cc:139
file::GetContents
absl::Status GetContents(const absl::string_view &filename, std::string *output, int flags)
Definition: file.cc:163
File::Close
bool Close()
Definition: file.cc:48
LOG
#define LOG(severity)
Definition: base/logging.h:420
file::WriteString
absl::Status WriteString(File *file, const absl::string_view &contents, int flags)
Definition: file.cc:176
file::Exists
absl::Status Exists(const absl::string_view &path, int flags)
Definition: file.cc:305
file::SetTextProto
absl::Status SetTextProto(const absl::string_view &filename, const google::protobuf::Message &proto, int flags)
Definition: file.cc:277
message
std::string message
Definition: trace.cc:395
logging.h
File::filename
absl::string_view filename() const
Definition: file.cc:135
File::WriteString
size_t WriteString(const std::string &line)
Definition: file.cc:126
file::GetTextProto
absl::Status GetTextProto(const absl::string_view &filename, google::protobuf::Message *proto, int flags)
Definition: file.cc:267
File::Size
size_t Size()
Definition: file.cc:40
File::Delete
static bool Delete(const char *const name)
Definition: file.cc:36
File::Open
bool Open() const
Definition: file.cc:137
int64
int64_t int64
Definition: integral_types.h:34
File::ReadLine
char * ReadLine(char *const output, uint64 max_length)
Definition: file.cc:98
file.h
file::WriteStringToFile
bool WriteStringToFile(const std::string &data, const absl::string_view &file_name)
Definition: file.cc:197
File
Definition: base/file.h:32
File::WriteLine
bool WriteLine(const std::string &line)
Definition: file.cc:130
File::ReadOrDie
void ReadOrDie(void *const buff, size_t size)
Definition: file.cc:66
operations_research::WriteProtoToFile
bool WriteProtoToFile(absl::string_view filename, const google::protobuf::Message &proto, ProtoWriteFormat proto_write_format, bool gzipped, bool append_extension_to_file_name)
Definition: file_util.cc:77
CHECK_EQ
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:697
file::SetBinaryProto
absl::Status SetBinaryProto(const absl::string_view &filename, const google::protobuf::Message &proto, int flags)
Definition: file.cc:287
File::Read
size_t Read(void *const buff, size_t size)
Definition: file.cc:70
uint64
uint64_t uint64
Definition: integral_types.h:39
operations_research::ReadFileToProto
bool ReadFileToProto(absl::string_view filename, google::protobuf::Message *proto)
Definition: file_util.cc:37
file::WriteProtoToFileOrDie
void WriteProtoToFileOrDie(const google::protobuf::Message &proto, const absl::string_view &file_name)
Definition: file.cc:262
File::Write
size_t Write(const void *const buff, size_t size)
Definition: file.cc:77
file::Delete
absl::Status Delete(const absl::string_view &path, int flags)
Definition: file.cc:297
file::Defaults
int Defaults()
Definition: base/file.h:119
File::WriteOrDie
void WriteOrDie(const void *const buff, size_t size)
Definition: file.cc:74
io.h
file
Definition: file.cc:141
File::OpenOrDie
static File * OpenOrDie(const char *const name, const char *const flag)
Definition: file.cc:81
proto
CpModelProto proto
Definition: cp_model_fz_solver.cc:107
file::Open
absl::Status Open(const absl::string_view &filename, const absl::string_view &mode, File **f, int flags)
Definition: file.cc:142
File::ReadToString
int64 ReadToString(std::string *const line, uint64 max_length)
Definition: file.cc:102
file::WriteProtoToASCIIFile
bool WriteProtoToASCIIFile(const google::protobuf::Message &proto, const absl::string_view &file_name)
Definition: file.cc:243
file::WriteProtoToASCIIFileOrDie
void WriteProtoToASCIIFileOrDie(const google::protobuf::Message &proto, const absl::string_view &file_name)
Definition: file.cc:250
file::OpenOrDie
File * OpenOrDie(const absl::string_view &filename, const absl::string_view &mode, int flags)
Definition: file.cc:154
operations_research::ReadFileToProtoOrDie
Proto ReadFileToProtoOrDie(absl::string_view filename)
Definition: file_util.h:41
CHECK
#define CHECK(condition)
Definition: base/logging.h:495
name
const std::string name
Definition: default_search.cc:808
File::Flush
bool Flush()
Definition: file.cc:46
File::Exists
static bool Exists(const char *const name)
Definition: file.cc:38