如何在离线时将 txt/csv 文件加载到 javascript 字符串/数组中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24346008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to load a txt/csv file into javascript string/array while offline
提问by Charles Clayton
I have a small html/javascript webpage that I want to run in a browser offline.
我有一个小的 html/javascript 网页,我想在浏览器中离线运行。
In the same way the page can include an image or a css file and use it while offline, I want to include a 3mb spreadsheet that the javascript reads into a 2d-array, and I'm hoping for something that would work on IE8 as well as modern browsers.
以同样的方式页面可以包含一个图像或一个 css 文件并在离线时使用它,我想包含一个 3mb 的电子表格,javascript 将它读入一个二维数组,我希望有一些可以在 IE8 上工作的东西以及现代浏览器。
C:\Folder\index.html
C:\Folder\code.js
C:\Folder\picture.png
C:\Folder\spreadsheet.csv
I've found multiple methods online like
我在网上找到了多种方法,例如
<script src="jquery-csv.js"></script>
var table = $.csv.toArrays("spreadsheet.csv");
or
或者
d3.text('spreadsheet.csv', function(error, _data){
var table = d3.csv.parseRows(_data);
});
or
或者
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {processData(data);}
});
});
But I tend to get same-origin policy errors such as:
但我倾向于得到同源策略错误,例如:
XMLHttpRequest cannot load file://data.txt. Received an invalid response. Origin 'null' is therefore not allowed access.
Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.
I can't seem to get these to work offline. How could I accomplish this?
我似乎无法让这些离线工作。我怎么能做到这一点?
Edit:
编辑:
I'm managed to get the following to work for a text file only on Firefoxusing the CSVToArray function found here, which is pretty sluggish with a file of this size, and a hidden iframe
.
我设法使用此处找到的 CSVToArray 函数使以下内容仅适用于Firefox上的文本文件,这对于这种大小的文件和隐藏的.iframe
Ultimately, it would be preferable if this was capable of running on IE8, and if I used a csv rather than a txt file, but at least it's a start.
最终,如果它能够在 IE8 上运行,并且如果我使用 csv 而不是 txt 文件,那将是可取的,但至少这是一个开始。
<iframe style="display:none;" id='text' src = 'file.txt' onload='read_text_file()'>
</iframe>
<script type="text/javascript" >
function read_text_file() {
var text = document.getElementById('text').contentDocument.body.firstChild.innerHTML;
var table = CSVToArray(text);
}
For IE8I managed to get this to work on a small scale but with the 3mb file it will occasionally crash the browser and will always accost the user with both a ton of warning messages that activex is being used and a wave of warnings that the script will slow down the computer.
对于IE8,我设法让它在小范围内工作,但使用 3mb 文件时,它偶尔会导致浏览器崩溃,并且总是会向用户发送大量正在使用 activex 的警告消息和一波脚本警告会使计算机变慢。
window.onLoad = readFileInIE("file.csv");
function readFileInIE(filePath) {
try {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.OpenTextFile(filePath, true);
var text = file.ReadAll();
var table = CSVToArray(text);
file.Close();
return fileContent;
} catch (e) {
if (e.number == -2146827859) {
alert('Unable to access local files due to browser security settings. ' +
'To overcome this, go to Tools->Internet Options->Security->Custom Level. ' +
'Find the setting for "Initialize and script ActiveX controls not marked as safe" and change it to "Enable" or "Prompt"');
}
}
}
回答by User
This might not work in IE8, but the HTML5 API is really useful for this. Just use:
这在 IE8 中可能不起作用,但 HTML5 API 对此非常有用。只需使用:
window.onload = function() {
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var textType = //format you'd like to recieve;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function(e) {
// apply magic here
}
reader.readAsText(file);
}
else
{
fileDisplayArea.innerText ="Sorry matey, can't help you with that filetype."
}
});
}
Then after that, a simple .html file that looks like this would do the trick:
然后,一个看起来像这样的简单 .html 文件就可以解决问题:
<html lang="en">
<head>
<script src="script.js"></script>
</head>
<body>
<div id="page-wrapper">
<div>
<input type="file" id="fileInput">
</div>
<pre id="fileDisplayArea"></pre> //display any output here
</div>
</body>
</html>
回答by pixelistik
As you have realized, any AJAX-based solution will be affected by security restrictions for local file access. Instead of finding browser-specific workarounds, you could go the JSONPway which avoids AJAX.
您已经意识到,任何基于 AJAX 的解决方案都会受到本地文件访问安全限制的影响。您可以采用避免 AJAX的JSONP方式,而不是寻找特定于浏览器的解决方法。
This would require you to pre-process your CSV data and save it in a more JS-friendly format. But this would be a good idea anyway, as native JS parsing is likely to perform better than a CSV parser implemented in JS.
这将要求您预处理您的 CSV 数据并将其保存为更 JS 友好的格式。但这无论如何都是一个好主意,因为原生 JS 解析可能比在 JS 中实现的 CSV 解析器执行得更好。
It could look roughly like this:
它大概是这样的:
index.html
索引.html
</head>
<body>
<div id="page-wrapper">
<div>
<input type="file" id="fileInput">
</div>
<pre id="fileDisplayArea"></pre> <!-- display any output here -->
</div>
<script src="script.js"></script>
<script src="data.js"></script>
</body>
</html>
script.js
脚本.js
function processData(data) {
// Your logic
// (will be called once data.js is loaded)
}
data.js
数据.js
processData([
["your", "data"]
]);
回答by Lex
My comment become too long.
我的评论变得太长了。
You can't include data files in the same way as media. The easiest way would be to preprocess the csv into a js array and then include the csv like js <script src="mydata.csv.js"></script>
.
您不能以与媒体相同的方式包含数据文件。最简单的方法是将 csv 预处理为 js 数组,然后像 js 一样包含 csv <script src="mydata.csv.js"></script>
。
By offline you mean local files and not public? The first suggestion would be to upgrade your browser. It doesn't quiet make sense if its a local file supporting all major browsers. Sorry I'm sure you have reasons why you can't. But upgrading would get around the non Ecmascript 5 support in ie8.
离线是指本地文件而不是公共文件?第一个建议是升级您的浏览器。如果它是一个支持所有主要浏览器的本地文件,它就没有任何意义。对不起,我相信你有理由不能。但是升级会绕过 ie8 中的非 Ecmascript 5 支持。
To get around the cross origin policy you'd have to run your file on a local webserver. So your html page would be on something like localhost:8080 and your csv localhost:8080/mydata.csv this gives privileges to the html to allow access to the csv file as they're now on the same domain. D3, jquerycsv should now work. Its a big security risk allowing any html file to access the filesystem freely.
要绕过跨源策略,您必须在本地网络服务器上运行您的文件。因此,您的 html 页面将位于 localhost:8080 和您的 csv localhost:8080/mydata.csv 上,这将授予 html 权限以允许访问 csv 文件,因为它们现在位于同一域中。D3,jquerycsv 现在应该可以工作了。允许任何 html 文件自由访问文件系统是一个很大的安全风险。
If a local server isn't an option. You have to select the file each time you load with an input field. This grants the browser permissions to access this file.
如果本地服务器不是一个选项。每次加载输入字段时都必须选择文件。这将授予浏览器访问此文件的权限。
After selecting the file, to read the contents for the main browsers (with Ecma5) look into FileReader on MDN, and an example of use can be found here. For ie8 + 9 there is VBscript supportto read files. You can use VB just like JS using <script type="text/vbscript"></script>
选择文件后,要读取主浏览器(使用 Ecma5)的内容,请查看MDN 上的 FileReader,可以在此处找到使用示例。对于 ie8 + 9,有VBscript 支持来读取文件。您可以像使用 JS 一样使用 VB<script type="text/vbscript"></script>
回答by Quasimodo's clone
If you really want to access local resources from a sever page then you need also a local page that allows the access. A local HTML page inside an <iframe>
could read the text file and post contents to the main page via window.postMessage()
.
如果您真的想从服务器页面访问本地资源,那么您还需要一个允许访问的本地页面。内部的本地 HTML 页面<iframe>
可以读取文本文件并将内容通过window.postMessage()
.
There might also be a way with HTML5 iframes and the sandbox
attribute, but not in IE9 and below.
HTML5 iframes 和sandbox
属性也可能有一种方法,但在 IE9 及以下版本中没有。
see:
看:
回答by Ryan B
It's not quite clear what you want to do.
目前还不清楚你想做什么。
Using jQuery it's possible to modify events that happen in the DOM. Using this you could potentially save the source code when you're done making changes. You would then need to replace your current source code with the saved code to use the changes the next time you open up the page. However, this would be a very laborious process and there are likely a number of better ways to accomplish what you want to do depending on what that is.
使用 jQuery 可以修改发生在 DOM 中的事件。使用它,您可以在完成更改后潜在地保存源代码。然后,您需要用保存的代码替换当前的源代码,以便在下次打开页面时使用更改。但是,这将是一个非常费力的过程,并且可能有许多更好的方法来完成您想要做的事情,具体取决于那是什么。
Also, in regards to Shota's post. You can't use AJAX unless you have a server running in the background. If you decide to set the system up on a server there are a number of options for accomplishing what you want.
另外,关于Shota的帖子。除非您有一台在后台运行的服务器,否则您不能使用 AJAX。如果您决定在服务器上设置系统,则有许多选项可以完成您想要的操作。