拖拽TXT文件实现回文查找:读取数据后无法使用的技术问题
Hey, let's break down the issues you're facing and fix them step by step:
Core Problems
You've hit two main roadblocks:
- FileReader is asynchronous: You're trying to use the file data before it's actually finished loading.
- GET requests aren't meant for large text data: Appending raw file content to a URL will cause encoding issues, length limits, and just plain doesn't follow HTTP best practices.
1. Fix the Async File Reading Issue
FileReader.readAsText() runs in the background, so your data variable is still empty when you try to use it outside the onload callback. You need to move your backend request logic inside the onload function to ensure you have the full file content first.
Here's the corrected frontend JS:
function dropHandler(ev) { console.log('File(s) dropped'); ev.preventDefault(); // Stop the browser from opening the file directly if (ev.dataTransfer.files) { const file = ev.dataTransfer.files[0]; // Only process text files if (file.type.includes("text")) { const reader = new FileReader(); // This callback runs ONLY after the file is fully loaded reader.onload = function(loadEvent) { const fileContent = loadEvent.target.result; console.log("Successfully loaded file content:", fileContent); // Now send the data to your backend sendPalindromeRequest(fileContent); }; reader.readAsText(file); } else { alert("Please drop a .txt file!"); } } } function dragOverHandler(ev) { ev.preventDefault(); // Allow drop action // Optional: Add visual feedback for the drop zone ev.currentTarget.style.background = "#f0f0f0"; } // Separate function for backend communication function sendPalindromeRequest(content) { $.post("/palindrome", { textContent: content }, function(response) { console.log("Palindrome results from backend:", response); // Here you can render results to the page, e.g.: // const resultDiv = document.getElementById("results"); // resultDiv.innerHTML = `<p>Found ${response.numValid} palindromic words:</p><ul>${response.words.map(w => `<li>${w}</li>`).join('')}</ul>`; }) .fail(function(error) { console.error("Request failed:", error); }); }
2. Update Your Crow Backend to Accept POST Requests
Your current route expects a string in the URL path, which is terrible for large text. Instead, we'll create a POST route that reads the text from the request body.
Also, I cleaned up your getPalindromes function to avoid duplicate entries and handle edge cases (like words not ending with a newline):
#include <unordered_map> #include <vector> #include <algorithm> #include <cctype> #include "crow_all.h" using namespace std; crow::json::wvalue getPalindromes(const string& data) { crow::json::wvalue result; unordered_map<string, bool> wordMap; // Use local map instead of global (thread-safe!) vector<string> validPalindromes; int count = 0; // Split text into words (handle newlines, spaces, and basic punctuation) string currentWord; for (char c : data) { // Keep alphanumeric characters only, convert to lowercase for case insensitivity if (isalnum(c)) { currentWord += tolower(c); } else if (!currentWord.empty()) { wordMap[currentWord] = true; currentWord.clear(); } } // Add the last word if the text doesn't end with a separator if (!currentWord.empty()) { wordMap[currentWord] = true; } // Find palindromic words or pairs for (const auto& entry : wordMap) { const string& word = entry.first; string reversedWord = word; reverse(reversedWord.begin(), reversedWord.end()); // Avoid duplicates (e.g., "ab" and "ba" only added once; "aba" added once) if (wordMap.count(reversedWord) && word <= reversedWord) { validPalindromes.push_back(word); count++; } } result["words"] = validPalindromes; result["numValid"] = count; return result; } int main() { crow::SimpleApp app; // POST route to accept text content CROW_ROUTE(app, "/palindrome").methods(crow::HTTPMethod::POST)([](const crow::request& req) { // Parse the JSON request body auto parsedBody = crow::json::load(req.body); if (!parsedBody) { return crow::response(400, "Invalid request body - expected JSON"); } // Extract the text content string text = parsedBody["textContent"].s(); auto palindromeData = getPalindromes(text); return crow::response(palindromeData); }); app.port(8080).run(); return 0; }
Quick Additional Tips
- Thread Safety: I replaced the global
hashmapwith a local one ingetPalindromes—this is crucial if your backend handles multiple requests at once, as global variables can cause race conditions. - Case Insensitivity: The code converts all characters to lowercase so "Racecar" and "racecar" are treated as the same word. Remove the
tolower(c)part if you want case-sensitive matching. - Word Parsing: The current code only keeps alphanumeric characters. Adjust the
isalnum(c)check if you need to handle accented characters or other symbols.
内容的提问来源于stack exchange,提问作者NeonFire

