Post

(C++) File IO - 과 pubsetbuf()

ifstream을 사용할지, fopen()을 사용할지는 얻어낸 결과를 어디에 담을 것인지에 따라 결정하면 된다. 어차피 얻어낸 데이터를 가공하는 과정에서 string으로 만들어야 한다거나, string의 메서드를 사용해야 편한 경우라면 그냥 ifstream을 사용한다.

왜냐면, char\*에서 string으로 변환하는건 새로운 string을 만들면서 생성자로 char\*데이터를 집어넣는 수 밖에 없는데이 때 Deep copy가 발생 한다. Shallow copy하는 방법 없나 찾아봤는데 아마 없는 것 같다. 그래서 문자열 데이터가 큰 경우 copy시 발생하는 오버헤드를 줄일 필요가 있기 때문에 아예 가공할 데이터의 타입을 따라가는 것이 좋다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <fstream>
#include <iostream>

  

using namespace std;

  

int main(int argc, char \*argv[]) {

ifstream ifs;

char buf[USER\_BUFSIZ];

ifs.rdbuf()->pubsetbuf(buf, USER\_BUFSIZ);  // setbuf before open().

ifs.open("C:\\Users\\umbum\\source\\repos\\a", std::ios::binary);

if (ifs.fail()) {

std::cout << "[\*] failed to open" << std::endl;

exit(EXIT\_FAILURE);

}

  


filebuf\* pbuf = ifs.rdbuf();

// pbuf->pubsetbuf(buf, BUF\_SIZE);  이렇게 해도 되고

// ifs.rdbuf()->pub..이렇게 해도 되나 ifs.getline()을 쓸 경우는 이게 낫고, pbuf->sgetn()을 쓸거면 위가 낫다.

// 이렇게 버퍼를 지정해 놓기만 하면, getline()이든 sgetn()이든 접근 시 알아서 버퍼를 채우고, 버퍼에서 가져오는 듯.

// 아직 데이터에 접근하지는 않았으니 여기서는 모두 00이 출력된다.

for (int i = 0; i < BUF\_SIZE; i++) {

printf("%02x ", buf[i]);

}

cout << "\n==============================================" << endl;

  


char b4[4];

pbuf->sgetn(b4, 4);    // 이 때 1. buf에 데이터가 채워지고, 2. b4에 데이터가 copy된다.

// pbuf->sgetn() 를 반복적으로 호출해주면 offset이 증가하며 알아서 다음 데이터를 가져온다.

// ifs.getline() 도 버퍼에서 가져오기 때문에 buffer를 사용하기 위해 꼭 sgetn()일 필요는 없다.

  


// pbuf->pubseekoff(-4, ifs.cur); 현재 위치 기준 뒤로 감기는 이렇게.

  


printf("%02x%02x%02x%02x", b4[0], b4[1], b4[2], b4[3]);  // 데이터 있다.

for (int i = 0; i < BUF\_SIZE; i++) {

printf("%02x ", buf[i]);

} // 여기도 채워져 있다.

ifs.close();

return 0;
}

pubsetbuf(buf, BUF\_SIZE)는 내부적으로 C++의 std::basic\_streambuf::setbuf(buf, BUF\_SIZE)를 호출하게 되는데, 이는 호출 하나 안하나 버퍼 사이즈에 변화를 주지 않는 C의 setbuf()와는 달리, user-provided buffer로 변경하면서 SIZE도 지정한 대로 변경하게 되므로 최적화에 사용할 수 있다. 따라서 오히려 C의 setvbuf()와 비슷하다.

This post is licensed under CC BY 4.0 by the author.