Skip to content

Commit a1fdef8

Browse files
committed
Split file io
1 parent db069b1 commit a1fdef8

3 files changed

Lines changed: 225 additions & 220 deletions

File tree

‎cpp/README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
1. IO
7272
1. [sstream](sstream.cpp)
7373
1. [iostream](iostream.cpp)
74+
1. [File IO](file_io.cpp)
7475
1. [thread](thread.cpp)
7576
1. [sleep_for](sleep_for.cpp)
7677
1. [atomic](atomic.cpp)

‎cpp/file_io.cpp‎

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
# file io
3+
4+
# ifstream
5+
6+
# ofstream
7+
8+
# fstream
9+
*/
10+
11+
#include "common.hpp"
12+
13+
void ios_write_fail(std::string path) {
14+
throw std::ios_base::failure("Error: Could not write to file: " + path);
15+
}
16+
17+
void ios_read_fail(std::string path) {
18+
throw std::ios_base::failure("Error: Could not read file: " + path);
19+
}
20+
21+
/**
22+
Read entire file into a string at once.
23+
*/
24+
void read_file(std::ifstream &ifs, std::string &data_read) {
25+
ifs.seekg(0, std::ios::end);
26+
size_t size = ifs.tellg();
27+
data_read.resize(size);
28+
ifs.seekg(0);
29+
ifs.read(&data_read[0], size);
30+
ifs.close();
31+
}
32+
33+
int main() {
34+
std::string path("fileio.tmp");
35+
std::string data("ab\n\nc\n");
36+
37+
// Write to file.
38+
{
39+
std::ofstream ofs(path);
40+
if (ofs) {
41+
ofs << data;
42+
ofs.close();
43+
} else {
44+
ios_write_fail(path);
45+
}
46+
}
47+
48+
/*
49+
# Read entire file at once
50+
51+
http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring
52+
53+
Best way seems to be to get file size, allocate, and read manually.
54+
*/
55+
{
56+
std::ifstream ifs(path);
57+
if (ifs) {
58+
std::string data_read;
59+
read_file(ifs, data_read);
60+
assert(data_read == data);
61+
} else {
62+
ios_read_fail(path);
63+
}
64+
}
65+
66+
/*
67+
# Copy file to another
68+
69+
# cp
70+
71+
# rdbuf
72+
73+
http://stackoverflow.com/questions/2141749/what-does-ifstreamrdbuf-actually-do
74+
*/
75+
{
76+
std::string data = "abc\ndef\n";
77+
std::string src_path = "src.tmp";
78+
std::string dst_path = "dst.tmp";
79+
// Create input file.
80+
{
81+
std::ofstream src(src_path, std::ios::binary);
82+
src << data;
83+
// 2 times 4 Gb.
84+
//for (int i = 0; i < 2; i++) {
85+
//for (int j = 0; j < 0xFFFFFFFF; j++) {
86+
//src << std::hex << j;
87+
//}
88+
//}
89+
src.close();
90+
}
91+
// Copy.
92+
std::ifstream src(src_path, std::ios::binary);
93+
std::ofstream dst(dst_path, std::ios::binary);
94+
dst << src.rdbuf();
95+
src.close();
96+
dst.close();
97+
// Check copy.
98+
{
99+
std::ifstream dst(dst_path, std::ios::binary);
100+
std::string data_read;
101+
read_file(dst, data_read);
102+
assert(data_read == data);
103+
src.close();
104+
}
105+
}
106+
107+
/*
108+
# Compare two files larger than memory.
109+
110+
TODO is there an easier way than reading each?
111+
*/
112+
{
113+
}
114+
115+
// # Append to file
116+
{
117+
std::ofstream ofs(path);
118+
119+
if (ofs) {
120+
ofs << data;
121+
ofs.close();
122+
} else {
123+
ios_write_fail(path);
124+
}
125+
126+
/*
127+
# open
128+
129+
# Reopen
130+
131+
Can be used to reopen ofstream with new properties.
132+
133+
Also consider clearing error flags if there can be any.
134+
*/
135+
//ofs.clear()
136+
ofs.open(path, std::ios::app);
137+
if (ofs) {
138+
ofs << data;
139+
ofs.close();
140+
} else {
141+
ios_write_fail(path);
142+
}
143+
144+
std::ifstream ifs(path);
145+
if (ifs) {
146+
std::string data_read;
147+
read_file(ifs, data_read);
148+
assert(data_read == data + data);
149+
} else {
150+
ios_read_fail(path);
151+
}
152+
}
153+
154+
/*
155+
# binary io
156+
157+
Use ios::binary, and the binary functions write and read.
158+
*/
159+
{
160+
// TODO
161+
//std::string path("binary.tmp");
162+
//std::vector<int> data{0x123, 0x456};
163+
//std::vector<int>::size_type size = data.size();
164+
//std::vector<int> data_read(size);
165+
//std::ofstream ofs(path, std::ios::binary);
166+
//if (ofs) {
167+
//ofs.write(&data[0], size);
168+
//ofs.close();
169+
//} else {
170+
//ios_write_fail(path);
171+
//}
172+
173+
//std::ifstream ifs(path);
174+
//if (ifs) {
175+
//std::string data_read;
176+
//read_file(ifs, data_read);
177+
//assert(data_read == data);
178+
//} else {
179+
//ios_read_fail(path);
180+
//}
181+
}
182+
183+
/*
184+
# error handling
185+
186+
# is_open vs bool cast
187+
188+
`is_open` false implies `operator bool()` false, but the converse is false: `operator bool()` is more strict.
189+
190+
<http://stackoverflow.com/questions/14920457/c-difference-between-casting-ifstream-to-bool-and-using-ifstreamis-open>
191+
192+
IO functions do not raise exceptions by default, but may be turned on.
193+
194+
The best standard exception to raise is probably `std::ios_base::failure`.
195+
196+
Relevant standard exceptions:
197+
198+
http://en.cppreference.com/w/cpp/io/ios_base/failure
199+
200+
SO thread:
201+
202+
http://stackoverflow.com/questions/9670396/exception-handling-and-opening-a-file
203+
*/
204+
{
205+
std::string path("i_dont_exist.tmp");
206+
std::ifstream ifs(path);
207+
if (ifs) {
208+
} else {
209+
try {
210+
throw std::ios_base::failure("Error: Could not write to file: " + path);
211+
} catch (std::ios_base::failure e) {
212+
std::clog << e.what() << std::endl;
213+
}
214+
215+
}
216+
}
217+
218+
/
219+
{
220+
}
221+
222+
// # ios::in: flag automatically set for ifstream, but not fstream
223+
//http://stackoverflow.com/questions/7463410/is-iosin-needed-for-ifstreams-opened-in-binary-mode
224+
}

0 commit comments

Comments
 (0)