如何将LeetCode代码及测试用例写入本地文件?Chrome扩展方案遇阻
解决Chrome扩展无法写入本地指定文件的方案
为啥直接写不了?
Chrome扩展的沙箱机制限制了直接访问本地任意路径的权限,所以没法直接把LeetCode的代码和测试用例写到C:/workspace/solution.cpp或test.txt,得换下面两种可行思路:
方案1:Native Messaging(推荐,自动写入指定路径)
这是Chrome官方提供的扩展与本地程序通信的机制,让本地脚本帮你完成文件写入操作:
操作步骤
编写本地处理脚本
用Python/Node.js写一个简单脚本,接收扩展传来的数据并写入指定路径。比如Python版本示例:import sys import json def main(): # 读取扩展发来的消息 raw_len = sys.stdin.read(4) if not raw_len: return msg_len = int.from_bytes(raw_len.encode('utf-8'), byteorder='little') msg = sys.stdin.read(msg_len) data = json.loads(msg) # 生成带头部的C++代码并写入文件 header = "#include <iostream>\nusing namespace std;\n\n" main_block = "\nint main() {\n // 可自行添加测试调用逻辑\n return 0;\n}" full_code = header + data['code'] + main_block with open('C:/workspace/solution.cpp', 'w', encoding='utf-8') as f: f.write(full_code) # 写入测试用例文件 with open('C:/workspace/test.txt', 'w', encoding='utf-8') as f: f.write(data['test_case']) # 给扩展回传完成信号 resp = json.dumps({"status": "done"}) sys.stdout.write((len(resp)).to_bytes(4, byteorder='little').decode('utf-8')) sys.stdout.write(resp) sys.stdout.flush() if __name__ == "__main__": main()配置扩展Manifest文件
在manifest.json中添加Native Messaging相关权限:{ "manifest_version": 3, "name": "LeetCode本地同步", "permissions": ["nativeMessaging", "activeTab"], "action": {"default_popup": "popup.html"}, "background": {"service_worker": "background.js"} }扩展端发送数据到本地脚本
先从LeetCode页面提取代码和测试用例,再发送给本地程序:// 提取LeetCode编辑器中的代码 function getSolutionCode() { // 注意:LeetCode页面DOM可能更新,需核对选择器有效性 const editorLines = document.querySelector('.monaco-editor .view-lines'); return editorLines ? editorLines.textContent.trim() : ''; } // 提取测试用例内容 function getTestCase() { const testInput = document.querySelector('#testcase-input textarea'); return testInput ? testInput.value.trim() : ''; } // 发送数据到本地程序 function sendToLocalApp() { const code = getSolutionCode(); const testCase = getTestCase(); const port = chrome.runtime.connectNative('com.your.domain.leetcode_sync'); port.postMessage({code, test_case: testCase}); port.onMessage.addListener(resp => { console.log('写入完成:', resp.status); }); }注册本地应用(Windows为例)
按照Chrome官方Native Messaging配置步骤,给本地脚本注册一个应用ID,让Chrome能够识别并调用它。
方案2:File System Access API(无需本地程序,需手动选择文件)
这个API允许用户授权扩展访问指定文件,之后可直接写入内容,适合不想折腾本地脚本的场景:
核心代码实现
// 写入带头部的C++解决方案文件 async function writeSolutionFile(code) { const header = "#include <iostream>\nusing namespace std;\n\n"; main_block = "\nint main() {\n // 自行添加测试逻辑\n return 0;\n}"; full_code = header + code + main_block; // 优先使用已保存的文件句柄,无则让用户选择文件 let fileHandle; const savedHandle = await chrome.storage.local.get('solFileHandle'); if (savedHandle.solFileHandle) { fileHandle = (await window.showOpenFilePicker({ types: [{description: 'C++文件', accept: {'text/x-c++src': ['.cpp']}}] }))[0]; } else { fileHandle = await window.showSaveFilePicker({ suggestedName: 'solution.cpp', types: [{description: 'C++文件', accept: {'text/x-c++src': ['.cpp']}}] }); await chrome.storage.local.set({solFileHandle: fileHandle}); } // 写入内容到文件 const writable = await fileHandle.createWritable(); await writable.write(full_code); await writable.close(); } // 写入测试用例文件 async function writeTestCaseFile(testCase) { let fileHandle; const savedHandle = await chrome.storage.local.get('testFileHandle'); if (savedHandle.testFileHandle) { fileHandle = (await window.showOpenFilePicker({ types: [{description: '文本文件', accept: {'text/plain': ['.txt']}}] }))[0]; } else { fileHandle = await window.showSaveFilePicker({ suggestedName: 'test.txt', types: [{description: '文本文件', accept: {'text/plain': ['.txt']}}] }); await chrome.storage.local.set({testFileHandle: fileHandle}); } const writable = await fileHandle.createWritable(); await writable.write(testCase); await writable.close(); } // 同步LeetCode数据到本地的入口函数 async function syncLeetCodeData() { const code = getSolutionCode(); const testCase = getTestCase(); await writeSolutionFile(code); await writeTestCaseFile(testCase); }
注意事项
- 第一次使用需要用户手动选择文件,后续会将文件句柄保存在扩展存储中,无需重复选择
- 该API仅支持HTTPS站点,LeetCode符合要求
提取LeetCode内容的小提醒
- LeetCode页面DOM结构可能会更新,需定期检查选择器是否有效
- 如果页面使用Monaco编辑器,也可以直接调用编辑器API获取代码:
monaco.editor.getEditors()[0].getValue()
内容的提问来源于stack exchange,提问作者waltwhittaker
相关产品推荐
相关产品推荐

