04.06.2017, 12:52
Hello,
Is there any way to read a file reverse?
Is there any way to read a file reverse?
hello test
tset olleh
test hello
Last line first, or completely reversed?
Imagine this is the content of your file: Код:
hello test Код:
tset olleh Код:
test hello |
File_LReverse(const fnamein[], const fnameout[])
{
// Open the files
new File:FIn = fopen(fnamein, io_read);
if(!FIn) return 0;
new File:FOut = fopen(fnameout, io_write);
if(!FOut)
{
fclose(FIn);
return 0;
}
new c, i = -1, j, buf[MAX_LINE_LENGTH], bool:newline; // c is the current character, i is the position (end - i), buf the temporary buffer and newline determines whether or not there was a new line at the very end (now start) of the file
do
{
fseek(FIn, i --, seek_end); // seek to end - i
c = fgetchar(FIn, 0, false); // Get character
if(c == '\r') continue;
if(c != EOF)
{
if(c != '\n') // Add to buffer
{
buf[j ++] = c;
}
else // New line - write buffer
{
if(i == -1) newline = true; // First character was a newline - keep that in mind
if(j != 0) // Buffer not empty - write
{
File_WReverse(FOut, buf, j);
fputchar(FOut, '\n', false);
j = 0;
}
}
}
else if(j != 0) // This writes the buffer because no more input is coming
{
File_WReverse(FOut, buf, j);
if(newline) fputchar(FOut, '\n', false);
j = 0;
}
}
while(c != EOF);
fclose(FOut);
fclose(FIn);
return 1;
}
File_WReverse(File:handle, const buf[], len) // This writes a string in reverse order. This is neccessary because our buffer is already reversed! Could be avoided by writing to the buffer in reversed order from the start
{
for(new i = len - 1; i >= 0; i --) fputchar(handle, buf[i], false);
}
File_LReverse("input.txt", "output.txt");
Okay, I wrote a function just for you to do it. There might be better ways and there is one issue - it ignores \r for now (\n will be kept). \n\r would result in two new lines.
It creates another file with the reverse line order. You can replace the second function with what you actually want to do - whenever buf[] is written a new line is added, but note that buf is still reversed at that point. Otherwise open the newly created file (inefficient though). It supports as many lines as you want, however there is a maximum line length (define MAX_LINE_LENGTH). PHP код:
Made this in a few minutes so if there are issues tell me (tests worked well). Example usage: Код:
File_LReverse("input.txt", "output.txt"); |
File_LReverse(const fnamein[], const fnameout[])
{
new File:FIn = fopen(fnamein, io_read);
if(!FIn) return 0;
new File:FOut = fopen(fnameout, io_write);
if(!FOut)
{
fclose(FIn);
return 0;
}
new c, totalchars, buf[MAX_LINE_LENGTH], flen, llen, bool:nline;
while((c = fgetchar(FIn, 0, true)) > 0) // Get file size and check if last line has a new line character
{
flen ++;
if(c == '\n') nline = false;
else nline = true;
}
if(nline) flen += 2; // Account for the missing new line at the very end of the file. This must be known before writing, otherwise the offsets of all other lines change!
fseek(FIn); // Reset pointer
while((llen = fread(FIn, buf)))
{
totalchars += llen; // Keep track of how many characters were already read in total
if(nline && totalchars == flen - 2 && llen < MAX_LINE_LENGTH-2) // If there was no new line at the very end and this is the last line, add "\r\n"
{
strcat(buf, "\r\n");
totalchars += 2;
}
fseek(FOut, flen - totalchars, seek_start); // Navigate to the correct offset in the new file (end - total characters read)
fwrite(FOut, buf);
}
fclose(FOut);
fclose(FIn);
return 1;
}
I came up with something way simpler, I guess.
Noticed that you can write to any position in a file and it will automatically adjust its size (fills with spaces). It now handles each line seperately, but directly writes them to the correct offset. PHP код:
|