Last active
July 21, 2021 18:41
-
-
Save kampersanda/fa2cf283b5fd2809f3def17579558aab to your computer and use it in GitHub Desktop.
後ろ向きにファイル読み込み
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
read_backward:read_backward.cpp | |
c++ -O3 -o read_backward read_backward.cpp -std=c++17 -Wall -Wextra -pedantic | |
clean: | |
rm -r -f read_backward |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <chrono> | |
#include <fstream> | |
#include <iostream> | |
static char OUTPUT[1024 * 1024]; // up to 1 MiB | |
// std::ifstreamのバッファの中身を確認 | |
void show_streambuf(std::ifstream& ifs) { | |
std::cout << "streambuf: "; | |
std::filebuf* buf = ifs.rdbuf(); | |
const std::streamsize num = buf->in_avail(); | |
for (std::streamsize i = 0; i < num; i++) { | |
std::cout << char(buf->sbumpc()); | |
} | |
for (std::streamsize i = 0; i < num; i++) { | |
buf->sungetc(); | |
} | |
std::cout << std::endl; | |
} | |
// std::ifstremによるシンプルな順方向読み込み | |
void read_forward(const char* filename) { | |
std::ifstream ifs(filename, std::ios::binary); | |
size_t i = 0; | |
for (char c; ifs.get(c);) { | |
OUTPUT[i++] = c; | |
} | |
ifs.close(); | |
} | |
// std::ifstremによるシンプルな逆方向読み込み | |
void read_backward(const char* filename) { | |
std::ifstream ifs(filename, std::ios::binary); | |
ifs.seekg(-1, std::ios::end); // 読み込みポインタを最後の文字に設定 | |
size_t i = 0; | |
for (char c; ifs.get(c);) { // 読み込みポインタ += 1 | |
// show_streambuf(ifs); | |
OUTPUT[i++] = c; | |
ifs.seekg(-2, std::ios::cur); // 読み込みポインタ -= 2 | |
} | |
ifs.close(); | |
} | |
// FILEによるバッファを使った逆方向読み込み | |
void read_backward_buffering(const char* filename) { | |
// バッファ | |
constexpr std::streamsize bufsize = 1024; | |
char buffer[bufsize]; | |
FILE* fp = fopen(filename, "rb"); | |
fseek(fp, 0L, SEEK_END); // 読み込みポインタをファイル末尾に設定 | |
const int64_t filesize = ftell(fp); // ファイルサイズ | |
size_t i = 0; | |
for (auto end = filesize; end > 0;) { | |
const auto beg = std::max<int64_t>(0, end - bufsize); | |
const auto readsize = end - beg; | |
fseek(fp, -readsize, SEEK_CUR); // 読み込みポインタを設定 | |
fread(buffer, 1, readsize, fp); // バッファに読み込み | |
fseek(fp, -readsize, SEEK_CUR); // 読み込んだ分をリセット | |
for (auto j = readsize - 1; j >= 0; --j) { | |
OUTPUT[i++] = buffer[j]; | |
} | |
end = beg; | |
} | |
fclose(fp); | |
} | |
int main(int argc, char** argv) { | |
if (argc != 2) { | |
std::cerr << "Argument error" << std::endl; | |
return 1; | |
} | |
const char* filename = argv[1]; | |
{ | |
const auto start_tp = std::chrono::high_resolution_clock::now(); | |
read_forward(filename); | |
const auto stop_tp = std::chrono::high_resolution_clock::now(); | |
const auto dur_ms = std::chrono::duration_cast<std::chrono::milliseconds>(stop_tp - start_tp); | |
std::cerr << "read_forward: " << dur_ms.count() << " ms" << std::endl; | |
} | |
{ | |
const auto start_tp = std::chrono::high_resolution_clock::now(); | |
read_backward(filename); | |
const auto stop_tp = std::chrono::high_resolution_clock::now(); | |
const auto dur_ms = std::chrono::duration_cast<std::chrono::milliseconds>(stop_tp - start_tp); | |
std::cerr << "read_backward: " << dur_ms.count() << " ms" << std::endl; | |
} | |
{ | |
const auto start_tp = std::chrono::high_resolution_clock::now(); | |
read_backward_buffering(filename); | |
const auto stop_tp = std::chrono::high_resolution_clock::now(); | |
const auto dur_ms = std::chrono::duration_cast<std::chrono::milliseconds>(stop_tp - start_tp); | |
std::cerr << "read_backward_buffering: " << dur_ms.count() << " ms" << std::endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment