C++读取实时更新CSV文件异常:重复读取初始值的解决咨询
Let's break down why your code is stuck reading the initial value and how to fix it:
The Root Cause
Your current code reopens the CSV file every second, but two key issues are blocking you from getting the updated value:
- File Locking: When the CSV is being continuously updated by another process (that keeps the file open), the default
std::ifstreamopening mode on Windows often locks the file or reads from a cached snapshot instead of the latest content. - Unhandled Stream States: If a read fails even once, the stream's error flags can persist and block future reads unless explicitly cleared.
Solution 1: Improve std::ifstream Usage
First, let's tweak your existing code to handle shared access and reset stream states properly:
#include <vector> #include <fstream> #include <iostream> #include <chrono> #include <thread> // For cross-platform sleep struct Node { double number; }; void readData(std::vector<Node>& Values) { Node Data; // Open in binary mode to avoid text mode quirks, and enable shared access std::ifstream file("file.csv", std::ios::in | std::ios::binary); if (!file.is_open()) { std::cerr << "Failed to open file – might be locked by another process!\n"; return; } // Reset file pointer to the start and clear any previous error flags file.seekg(0, std::ios::beg); file.clear(); if (file >> Data.number) { Values.push_back(Data); std::cout << "Successfully read: " << Data.number << "\n"; } else { std::cerr << "Failed to parse data from file!\n"; } // Explicitly close the file to release resources immediately file.close(); } int main() { std::vector<Node> Values; while (true) { readData(Values); // Cross-platform sleep (replaces Windows-specific _sleep) std::this_thread::sleep_for(std::chrono::seconds(1)); } return 0; }
Key Changes Here:
- Binary Mode:
std::ios::binaryhelps avoid unexpected newline conversions and improves compatibility with shared file access on Windows. - Stream Reset:
seekg(0, std::ios::beg)ensures we always read from the start of the file, andfile.clear()resets any error flags that might have been set by a failed read. - Cross-Platform Sleep: Replaced
_sleepwithstd::this_thread::sleep_forto make the code work on non-Windows systems.
Solution 2: Windows API for Precise File Control
If Solution 1 still doesn't work (because the writing process has strict locking), use the Windows API's CreateFile to explicitly allow shared read/write access:
#include <vector> #include <iostream> #include <windows.h> #include <cstdlib> // For atof #include <chrono> #include <thread> struct Node { double number; }; bool readLatestValue(double& value) { // Open the file with explicit shared access rights HANDLE hFile = CreateFileA( "file.csv", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, // Allow other processes to read/write while we access NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { std::cerr << "Failed to open file. Error code: " << GetLastError() << "\n"; return false; } char buffer[256]; DWORD bytesRead; bool readSuccess = ReadFile(hFile, buffer, sizeof(buffer)-1, &bytesRead, NULL); if (readSuccess && bytesRead > 0) { buffer[bytesRead] = '\0'; // Null-terminate the buffer value = atof(buffer); } else { std::cerr << "Failed to read file. Error code: " << GetLastError() << "\n"; readSuccess = false; } CloseHandle(hFile); return readSuccess; } void readData(std::vector<Node>& Values) { Node Data; if (readLatestValue(Data.number)) { Values.push_back(Data); std::cout << "Read latest value: " << Data.number << "\n"; } } int main() { std::vector<Node> Values; while (true) { readData(Values); std::this_thread::sleep_for(std::chrono::seconds(1)); } return 0; }
Why This Works:
CreateFile lets you specify FILE_SHARE_READ | FILE_SHARE_WRITE, which tells Windows that other processes can modify the file while you're reading it. This bypasses the default locking behavior that was causing you to read cached initial values.
Final Notes
- If the writing process is using exclusive file access, even these solutions might fail – check that the program updating the CSV isn't locking the file completely.
- For production code, consider adding retry logic if the file is temporarily locked instead of just failing silently.
内容的提问来源于stack exchange,提问作者michaelprogramm

