[英]C copy file contents from EOF to SOF
我的程序幾乎可以正常工作。 預期目的是從頭讀取文件,然后將內容復制到目標文件。 但是,令我困惑的是lseek()
方法,所以我應該如何設置偏移量。
我目前的src
內容是:
1號線
2號線
3號線
目前,我在目標文件中得到的是:
3號線
2號
e 2 ...
據我了解,調用int loc = lseek(src, -10, SEEK_END);
將源文件中的“光標”移動到結束,然后將其從EOF偏移到SOF 10個字節,而loc的值將是我減去偏移后的文件大小。 但是,經過7個小時的C,我在這里幾乎死了。
int main(int argc, char* argv[])
{
// Open source & source file
int src = open(argv[1], O_RDONLY, 0777);
int dst = open(argv[2], O_CREAT|O_WRONLY, 0777);
// Check if either reported an erro
if(src == -1 || dst == -1)
{
perror("There was a problem with one of the files.");
}
// Set buffer & block size
char buffer[1];
int block;
// Set offset from EOF
int offset = -1;
// Set file pointer location to the end of file
int loc = lseek(src, offset, SEEK_END);
// Read from source from EOF to SOF
while( loc > 0 )
{
// Read bytes
block = read(src, buffer, 1);
// Write to output file
write(dst, buffer, block);
// Move the pointer again
loc = lseek(src, loc-1, SEEK_SET);
}
}
lseek()
不會更改或返回文件大小。 返回內容,其中“光標”設置為位置 。 所以當你打電話
loc = lseek(src, offset, SEEK_END);
兩次,它將始終再次將光標設置到相同位置。 我猜你想做這樣的事情:
while( loc > 0 )
{
// Read bytes
block = read(src, buffer, 5);
// Write to output file
write(dst, buffer, block);
// Move the pointer again five bytes before the last offset
loc = lseek(src, loc+offset, SEEK_SET);
}
如果行長可變,則可以執行以下操作:
// define an offset that exceeds the maximum line length
int offset = 256;
char buffer[256];
// determine the file size
off_t size = lseek( src, 0, SEEK_END );
off_t pos = size;
// read block of offset bytes from the end
while( pos > 0 ) {
pos -= offset;
if( pos < 0 ) {
//pos must not be negative ...
offset += pos; // in fact decrements offset!!
pos = 0;
}
lseek( src, pos, SEEK_SET );
// add error checking here!!
read(src, buffer, offset );
// we expect the last byte read to be a newline but we are interested in the one BEFORE that
char *p = memchr( buffer, '\n', offset-1 );
p++; // the beginning of the last line
int len = offset - (p-buffer); // and its length
write( dst, p, len );
pos -= len; // repeat with offset bytes before the last line
}
我想你應該使用SEEK_CUR
,而不是SEEK_END
在您的最終調用lseek()
// Set file pointer location to the end of file
int loc = lseek(src, offset, SEEK_END);
// Read from source from EOF to SOF
while( loc > 0 )
{
// Read bytes
block = read(src, buffer, 5);
// Write to output file
write(dst, buffer, block);
// Move the pointer again
lseek(src, -10, SEEK_CUR);
}
您也可以這樣做:
// Set file pointer location to the end of file
int loc = lseek(src, offset, SEEK_END);
// Read from source from EOF to SOF
while( loc > 0 )
{
// Read bytes
block = read(src, buffer, 5);
// Write to output file
write(dst, buffer, block);
// Move the pointer again
loc -= 5;
lseek(src, loc, SEEK_SET);
}
從您的一些評論看來,您想要顛倒文本文件中各行的順序。 不幸的是,您不會通過這樣一個簡單的程序來實現這一點。 您可以采取幾種方法,具體取決於您要變得多么復雜,文件有多大,手頭有多少內存,想要多快等。
這是我想到的一些不同的想法:
一次將整個源文件讀取到一個存儲塊中。 向前掃描存儲塊以查找換行符,並記錄每行的指針和長度。 將這些記錄保存到堆棧中(您可以使用動態數組或C ++中的STL向量),然后編寫輸出文件,只需從堆棧中彈出一行記錄(在數組中向后移動)並寫入,直到堆棧是空的(您已經到達數組的開頭。)
從輸入文件的末尾開始,但是對於每一行,請逐個字符地向后搜索,直到找到開始上一行的換行為止。 再次向前搜索該換行符,然后讀入該行。 (您現在應該知道它的長度。)或者,您可以在緩沖區中建立反向字符,然后將它們向后寫出。
從頭到尾一次拉入整個文件塊(可能是扇區)。 在每個塊中,以與上述方法類似的方式定位換行符,除了現在您已經在存儲器中存儲了字符,因此無需進行任何反向或多余地拉入字符。 但是,此解決方案將更加復雜,因為行可以跨越塊邊界。
可能會有更多精心設計/巧妙的把戲,但這是更明顯,直接的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.