如何用浏览器读取本地文件(兼容IE8),new bing能帮我吗?
浏览器读写文件?
有一份老旧而精巧的代码(2006或更早),带js的html,可以只用浏览器来处理一些二进制存档数据。
文件的读写怎么办?通过变动的方法来完成。
利用十六进制编辑软件如WinHEX,直接复制十六进制数值为字符串,贴到一个TextArea以输入;
同样处理过的数据也是生成十六进制字符串,用WinHEX以ASCII Hex的格式粘贴到新文件中。
很巧妙,也有点繁琐。
FileReader:
最近找到了该程序的汉化版,也是好多年前的了,发现里面设计了直接用<input>来加载文件的功能,用的vbs调用Msxml2.XMLHTTP对象来处理。
可是现在的浏览器基本不支持vbs了,就想改一下,用js来完成。
上网搜索了一堆,XMLHTTP/XMLHttpRequest的代码,有些需要服务器端支持,结果都不理想,或浏览器显示无法创建对象之类的。
刚好new bing的申请也通过了,一番对话式交流,新搜索引擎初试身手,效果不错,直接给出了示例代码。
只要是支持HTML5的现代浏览器,调用FileReader,那叫一个驾轻就熟!
依葫芦画瓢,花了一点功夫也就改造完成了。
这时又回想起一个问题,旧浏览器(IE10以下,原网银的最爱)怎么办。
如何兼容IE8?
有这个必要吗?
都3202年了,不支持HTML5、不支持ES6的浏览器就该回垃圾堆或封存至博物馆!
网银都终于要求兼容Edge啦!
但无聊也是无聊,继续随便搜搜“JS读取本地文本文件 浏览器兼容”,结果是有一大堆,可大多都是标题党。
在有些参考资料中,提到使用“Microsoft.XMLDOM”对象,试了好久,更适用于文本数据,FSO对象貌似也只能OpenTextFile或OpenAsTextStream。
以上方法,读取到的数据都少了很多非可打印/显示字符,当然不行。
还是要用ADODB.Stream,因为它有个方法Read(),可读取二进制数据流。
ADODB.Stream:
碰到两个问题:
- 浏览器无法创建对象。安全问题,容易给恶意程序随意读写客户的数据,一般不开放这个功能,改改注册表,强行开通吧。
- 读不到二进制数据。在IE8中调试程序,一到adodb.Read()后面,产生的东西却不是个object,typeof测试一下,unknown...
正想放弃adodb.stream,又搜到一些资料,既然.Read()不行,严肃地建议我用.ReadText()。
读取文本,用来处理二进制数据,这也行?
adodb.stream支持对字符集的转换处理,刚好有个神奇的字符集系列:
ISO-8859-1~15
ISO-8859-1(又叫Latin1或Windows-1252),MySQL人士比较熟悉,软件默认的拉丁西欧字符集,它的特点在于对单字节完全编码,1Byte=8bit, 它把所有256个码位全部都排满了。
所以,可用它存储任意二进制数据而不会丢失。
至于编码解码的处理是另外一回事,后续折腾也是由此……
程序好像改造成功,一个数据也没少,不管是否为可打印/显示字符,或者对拉丁来说全是合法字符!
然~~而,读取的数据好像有几个地方有差异!不多、但是不同!
换成ISO-8859-15,差异少了许多,但还是有差异。
十万个为什么?
差异原因
为什么网上的示例代码对图像、声音文件进行复制都不出错,我加载数据到程序中就有差异?
继续追踪调试,找到了端倪,有几个特定的数据,读取出来就变了。
比如84就固定转化为1E、80变AC……
只是文件复制的话,持续沿用ISO-8859 Latin字符集,同一个管理,怎么In/Out、Read/Write,数据都不会变。
但是一旦用js将数据读取为数值,在转化为16进制字符串时,问题出现了。
因JavaScript引擎内部,所有字符都用 Unicode 表示。而Latin1字符集中的某些符号,在Unicode中是多字节编码。
而ISO-8859-15中,这样的字符比较少而已,当然,所处码位也不同。
比如拉丁字符中用1字节0x80表示了“€”,而在Unicode中编码是0x20AC;而“„”则0x84变成了0x201E,等等……
刚好对上!
原二进制数据就这样被转换了,编码冲突,怎么还原?
再问new bing,多次给出的代码也存在这个问题,继续追问Unicode的编码问题,认错态度非常好,但是没有解决方案。
那只能这样了:
手工转换
懒得写代码,new bing也不理我。
刚好又搜索到一位国外友人的代码,问题解决,但是TA用的是437字符集,直接把256个字符的编码做了个对照查询表,转换函数非常之长,我也不想改用437了。
我直接输出了ISO-8859-15字符集所有00~FF用js转换为数值的结果,和真实二进制数据相比,也就存在8处不同的Unicode字符嘛,处理过程中查询修正一下就行了。
搞定!
还是要自己写……其实也不费力。
示例,读取并显示为HEX
<input type="file" id="fileInput" title="Choose a file" onchange="dispHex(this);"/>
<br />
<h1 id='hexh1'>16进制</h1>
<textarea id='display' title='16进制内容显示' style='width:600px;height:400px;'></textarea>
<script language='javascript' type='text/javascript'>
function dispHex(f){
var hexString = "";
//获取显示框
var disp = document.getElementById("display");
if (window.FileReader){
alert("H5");
var file = f.files[0];
var reader = new FileReader();
//添加读取完成事件
reader.onload = function(e) {
var buffer = e.target.result;
var array = new Uint8Array(buffer);
for (var i = 0; i < array.length; i++) {
//将每个元素转化为16进制字符串,并补齐两位,用空格分隔
var s= '0' + array[i].toString(16);
s = s.substr(s.length - 2, 2);
hexString += s;
}
//将字符串显示在页面上
disp.textContent = hexString;
};
reader.readAsArrayBuffer(file);
}
else if (typeof window.ActiveXObject != 'undefined') {
alert("IE8及以下,请启用ActiveX控件交互!\n如不能打开文件,请将网页下载至本地运行。\n如何开启Adodb.Stream请自行搜索……");
var file = f.value; //网页不在本地,则为fakepath
//f.select();
//file = document.selection.createRange().text
hexString = AdodbReadHexFromFile(file);
disp.value = hexString;
}
else alert("Other!");
}
//使用ActiveX,要求浏览器开启相应功能和安全设置
function AdodbReadHexFromFile(fileURL){
var binStr, hexStr="";
//ADODB方式,需启用:https://www.cnblogs.com/weiweictgu/archive/2007/03/02/661940.html
var inStream = new ActiveXObject("ADODB.Stream");
inStream.Type = 2; //adTypeBinary = 1,2为Text
inStream.Open();
//Latin1(Windows-1252):ISO-8859-1)单字节完全编码
inStream.CharSet = "iso-8859-15";
//转换结果iso-8859-15比iso-8859-1更接近原数据?更少收录Unicode中的多字节符号。
inStream.LoadFromFile(fileURL);
//Read()为二进制数组,可结果typeof=unknown.WHY.?.所以用ReadText变通...
binStr = inStream.ReadText();
inStream.Close();
inStream = null;
//binStr2HEX
//https://www.codeproject.com/articles/17825/reading-and-writing-binary-files-using-jscript
var ISO885915=[8364,352,353,381,382,338,339,376]; //单字节集中包含的Unicode字符编码
var HexOrg=['A4','A6','A8','B4','B8','BC','BD','BE']; //上述字符Latin真实16进制值,由比较而来,437/Latin1同理可得
var isoCheckNum=ISO885915.length;
for (var i=0 ; i<binStr.length ; i++) {
var curCode=binStr.charCodeAt(i);
//charCodeAt可能会解释成多字节,有字符会被错误转换,如'€',无视CharSet LatinX
//因JavaScript引擎内部,所有字符都用 Unicode 表示
var s,isUnicode=false;
if(curCode>=256){
var j; //IE8不支持indexOf()
for(j=0;j<isoCheckNum;j++) if(curCode==ISO885915[j]) break;
if(j<isoCheckNum) isUnicode=true;
}
if(isUnicode) s=HexOrg[j]; //查表将Unicode字符转换回正确的单字节16进制
else{
s= '0' + curCode.toString(16).toUpperCase();
//确保是两位数的HEX
var bytes = 2;
//var bytes=Math.floor(s.length/2)*2; //多字节内容处理
s = s.substr(s.length - bytes, bytes);
}
hexStr += s;
}
return hexStr;
}
</script>
后记
js生成文件供浏览器下载,现代浏览器用blob加createObjectURL轻松搞定。
在分离FileReader一段代码至子函数时,对异步操作的处理还闹过小问题,Promise的逻辑还真是有些不适合本中老年。
IE8?不想玩了。
奇怪地是,再过了几天,问new bing本文类似的问题,它拒绝给出示例代码,说它不会,说它没有记忆,说IE8没法处理这个读取本地二进制文件的问题……
如何用浏览器读取本地文件(兼容IE8),new bing能帮我吗?的更多相关文章
- 前台JS(type=‘file’)读取本地文件的内容,兼容各种浏览器
[自己测了下,能兼容各种浏览器,但是读取中文会出现乱码.自己的解决方法是用notepad++把txt文件编码改为utf-8(应该是和浏览器编码保持一致吧?..)] 原文 http://blog.cs ...
- H5读取本地文件操作
H5读取本地文件操作 本文转自:转:http://hushicai.com/2014/03/29/html5-du-qu-ben-di-wen-jian.html感谢大神分享. 常见的语言比如php. ...
- FileReader读取本地文件
FileReader是一种异步读取文件机制,结合input:file可以很方便的读取本地文件. 一.input:type[file] file类型的input会渲染为一个按钮和一段文字.点击按钮可打开 ...
- .NET 读取本地文件绑定到GridViewRow
wjgl.aspx.cs: using System; using System.Collections; using System.Configuration; using System.Data; ...
- 手工创建tomcat应用,以及实现js读取本地文件内容
手工创建tomcat应用: 1.在webapps下面新建应用目录文件夹 2.在文件夹下创建或是从其他应用中复制:META-INF,WEB-INF这两个文件夹, 其中META-INF清空里面,WEB-I ...
- 【转】flash air中读取本地文件的三种方法
actionscript中读取本地文件操作有两种代码如下 1.使用File和FileStream两个类,FileStream负责读取数据的所以操作:(同步操作) var stream:FileStre ...
- python 读取本地文件批量插入mysql
Uin_phone.txt 本地文件内容 有1000条,这里只是展示前几条,供参考 133584752 133584759 133584764 133584773 133584775 13358477 ...
- spark读取本地文件
/** * Read a text file from HDFS, a local file system (available on all nodes), or any * Hadoop-supp ...
- 让Chrome支持Ajax/$http方式读取本地文件
在开发中经常写些小demo调试一下插件什么的 数据源又经常手动构造分离为一个单独的文件.用ajax或$http去访问时总是拒绝访问.这个时候可以给Chrome的快捷图标加启动参数,让浏览器允许js访问 ...
- HTML5读取本地文件
本文转自:转:http://hushicai.com/2014/03/29/html5-du-qu-ben-di-wen-jian.html感谢大神分享. 常见的语言比如php.shell等,是如何读 ...
随机推荐
- 第一个知识点:import 和 export
//全部导入import people from './example' //有一种特殊情况,即允许你将整个模块当作单一对象进行导入//该模块的所有导出都会作为对象的属性存在import * as e ...
- AUTO Uninstaller 9.3.28 最新免费密钥绿色版下载【转载】
大家在使用autodesk系列软件之后,想要彻底卸载清除重新安装却发现无法卸载或者清除不干净的问题,这该怎么办?这里小编就给大家分享一个好用的CAD清理工具AUTO Uninstaller,轻松卸载a ...
- JAVA、Tomcat服务器
JAVA如何配置服务器 Tomcat服务器: 1.Web开发中的常见概念: (1)B/S系统和C/S系统 Brower/Server:浏览器 服务器 系统 ----- 网站 Client/Server ...
- 学习JavaScript第一周
三种输出方式,console.log.element.write.alert(): 简单数据类型:数值型.字符串型.布尔类型.undefined.null 复杂数据类型:对象 数据类型的转换:字符串转 ...
- flutter 环境配置以及我的第一个flutter程序(Hello World)
电脑配置: 操作系统: Windows 7 或更高版本 (64-bit) 磁盘空间: 400 MB (不包括Android Studio的磁盘空间). Windows下所需安装有: 1.Flutter ...
- python中的变量定义
1 变量名:由下划线.字母和数字组成 2 python中变量名的特殊含义: xx:标准的标识符,共有的 _xx:只是在from - import *时是不会被导入的,其他导入方式会被引入 隐藏变量还有 ...
- 1js 高级
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- houdini python 配置 vscode 环境
一.在我的文档python文件夹中找到houdini.env文件,打开,加入语句 EDITOR = vscode路径 例如:EDITOR = D:\vscode\Microsoft VS Code\C ...
- 8、HTTP Cookie管理器
如果有需要加的cookie 就选择添加 如果没有特殊的 就默认就好了 第一次访问是没有cookie的 会话 session Cookie 是明文的 Session id 是保存在cookie里 ...
- Java工程结构 应用分层
(一) 应用分层 1. [推荐]图中默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于 Web 层,也可以直接依赖于 Service 层,依此类推: • 开放接口层:可直接封装 Se ...