크기와 개수를 인수로 취하는 fread / fwrite의 근거는 무엇입니까?
우리는 왜 fread와 fwrite가 멤버 당 크기를 취하고 버퍼와 크기를 취하는 대신 읽고 / 쓰기 된 멤버의 수를 계산하고 반환하는 이유에 대해 여기서 논의했습니다. 우리가 생각해 낼 수있는 유일한 용도는 플랫폼 정렬로 균등하게 나눌 수 없으므로 패딩 된 구조체 배열을 읽고 / 쓰려는 경우이지만이 선택을 보장 할만큼 일반적 일 수는 없습니다. 디자인.
에서 FREAD (3) :
fread () 함수는 stream이 가리키는 스트림에서 각 크기 바이트 길이의 데이터의 nmemb 요소를 읽고 ptr이 지정한 위치에 저장합니다.
fwrite () 함수는 각 크기 바이트 길이의 데이터의 nmemb 요소를 stream이 가리키는 스트림에 기록하여 ptr이 지정한 위치에서 가져옵니다.
fread () 및 fwrite ()는 성공적으로 읽거나 쓴 항목 수 (즉, 문자 수가 아님)를 반환합니다. 오류가 발생하거나 파일 끝에 도달하면 반환 값은 짧은 항목 수 (또는 0)입니다.
그것은 fread 가 구현 되는 방법을 기반으로합니다 .
단일 UNIX 사양에 따르면
각 개체에 대해 크기 호출이 fgetc () 함수에 대해 수행되고 결과는 읽은 순서대로 개체를 정확히 오버레이하는 부호없는 문자 배열에 저장됩니다.
fgetc 에는 다음과 같은 메모도 있습니다.
fgetc ()는 바이트에서 작동하므로 여러 바이트 (또는 "다중 바이트 문자")로 구성된 문자를 읽으려면 fgetc ()를 여러 번 호출해야 할 수 있습니다.
물론 이것은 UTF-8과 같은 멋진 가변 바이트 문자 인코딩보다 이전입니다.
SUS는 이것이 실제로 ISO C 문서에서 가져온 것이라고 언급합니다.
fread (buf, 1000, 1, stream) 및 fread (buf, 1, 1000, stream)의 차이점은 첫 번째 경우에 파일이 더 작고 두 번째 경우 파일의 모든 것을 1000 바이트 이하로 가져옵니다.
이것은 순수한 추측이지만, 과거에는 많은 파일 시스템이 하드 드라이브의 단순한 바이트 스트림이 아니 었습니다.
많은 파일 시스템이 레코드 기반이므로 효율적인 방식으로 이러한 파일 시스템을 만족 시키려면 항목 수 ( "레코드")를 지정해야합니다. 그러면 fwrite / fread가 저장소에서 바이트 스트림이 아닌 레코드로 작동 할 수 있습니다.
여기에서 해당 기능을 수정하겠습니다.
size_t fread_buf( void* ptr, size_t size, FILE* stream)
{
return fread( ptr, 1, size, stream);
}
size_t fwrite_buf( void const* ptr, size_t size, FILE* stream)
{
return fwrite( ptr, 1, size, stream);
}
fread()
/ 에 대한 매개 변수에 대한 이론적 근거 fwrite()
는 K & R 사본을 오래 전에 잃어 버렸기 때문에 추측 만 할 수 있습니다. 아마도 Kernighan과 Ritchie가 바이너리 I / O를 수행하는 것이 객체 배열에서 가장 자연스럽게 수행 될 것이라고 생각했을 수 있다고 생각합니다. 또한 블록 I / O가 구현하는 것이 더 빠르거나 더 쉬울 것이라고 생각했을 수도 있습니다.
심지어 그 C 표준을 지정 불구 fread()
하고 fwrite()
측면에서 구현 fgetc()
하고 fputc()
, 표준은 C가 K & R에 의해 표준 힘에 지정된 일을하지 원래 디자이너의 아이디어에 있었던 것으로 정의 된 후에도 오랫동안 존재로 온 것을 기억한다. K & R의 "The C Programming Language"에서 말한 내용이 언어가 처음 설계되었을 때와 같지 않을 수도 있습니다.
마지막으로 PJ Plauger가 fread()
"The Standard C Library"에서 말한 내용 은 다음과 같습니다.
는 IF
size
(두 번째) 인수가 1보다 큰, 당신은 함수가도를 읽을 여부를 확인할 수 없습니다size - 1
그것을보고하는 것 이상 추가 문자. 원칙적으로, 당신은 함수를 호출 더 낫다fread(buf, 1, size * n, stream);
대신fread(buf, size, n, stream);
기본적으로 그는 fread()
인터페이스가 손상 되었다고 말합니다 . 들어 fwrite()
내가 동의하지 않을 성명 - 그가 그 노트, "이 큰 단점이되지 않도록 쓰기 오류는 일반적으로 드물다".
파일 I / O가 구현 된 방식으로 돌아갈 가능성이 있습니다. (예전으로) 블록 단위로 파일을 쓰거나 읽은 다음 모든 것을 한꺼번에 쓰는 것이 더 빠를 수 있습니다.
C에 함수 과부하가 없기 때문이라고 생각합니다. 일부가 있으면 크기가 중복됩니다. 그러나 C에서는 배열 요소의 크기를 결정할 수 없으므로 하나를 지정해야합니다.
이걸 고려하세요:
int intArray[10];
fwrite(intArray, sizeof(int), 10, fd);
fwrite가 허용 된 바이트 수를 작성하면 다음과 같이 작성할 수 있습니다.
int intArray[10];
fwrite(intArray, sizeof(int)*10, fd);
그러나 그것은 비효율적입니다. sizeof (int) 배 더 많은 시스템 호출이 있습니다.
고려해야 할 또 다른 점은 일반적으로 배열 요소의 일부가 파일에 기록되는 것을 원하지 않는다는 것입니다. 정수를 원하거나 아무것도 원하지 않습니다. fwrite는 성공적으로 작성된 여러 요소를 반환합니다. 따라서 요소의 2 바이트 만 작성되었다는 사실을 발견하면 어떻게 하시겠습니까?
일부 시스템 (정렬로 인해)에서는 복사본을 만들고 이동하지 않고는 1 바이트의 정수에 액세스 할 수 없습니다.
크기와 개수에 대해 별도의 인수를 갖는 것은 부분 레코드 읽기를 피할 수있는 구현에 유리할 수 있습니다. 파이프와 같은 것에서 단일 바이트 읽기를 사용하는 경우 고정 형식 데이터를 사용하더라도 레코드가 두 읽기로 분할 될 가능성을 허용해야합니다. 대신 293 바이트를 사용할 수있을 때 각각 10 바이트 씩 최대 40 개의 레코드에 대한 비 차단 읽기를 요청할 수 있고 다음 읽기를 위해 3 바이트를 준비하면서 시스템이 290 바이트 (전체 레코드 29 개)를 반환하도록 할 수 있습니다. 훨씬 더 편리합니다.
fread의 구현이 그러한 의미를 어느 정도 처리 할 수 있는지는 알 수 없지만 지원을 약속 할 수있는 구현에는 확실히 유용 할 수 있습니다.
'developer tip' 카테고리의 다른 글
PostgreSQL의 함수 내에서 SELECT 결과를 반환하는 방법은 무엇입니까? (0) | 2020.09.10 |
---|---|
ScrollView 내의 ViewPager가 올바르게 스크롤되지 않습니다. (0) | 2020.09.10 |
OVER_QUERY_LIMIT 응답을받지 않고 20 개 주소를 지오 코딩하려면 어떻게해야합니까? (0) | 2020.09.10 |
f : viewAction / preRenderView 대 PostConstruct를 언제 사용합니까? (0) | 2020.09.10 |
친구에게 비공개 메시지 보내기 (0) | 2020.09.10 |