如何用瀏覽器讀取本地文件(相容IE8),new bing能幫我嗎?

来源:https://www.cnblogs.com/repus/archive/2023/03/27/17260978.html
-Advertisement-
Play Games

現代瀏覽器用FileReader,老版本IE載入adodb.stream用ISO-8859-1~15字元集處理讀取,要註意與Unicode的編碼衝突。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讀取本地文本文件 IE8相容”,結果是有一大堆,可大多都是標題黨。

在有些參考資料中,提到使用“Microsoft.XMLDOM”對象,試了好久,更適用於文本數據;

FSO對象貌似也只能OpenTextFile或OpenAsTextStream。

以上方法,讀取到的是文本字元串數據,都少了很多非可列印/顯示字元,當然不行。

還是要用ADODB.Stream,因為它有個方法Read(),可讀取二進位數據流。

ADODB.Stream:

碰到兩個問題:

  1. 瀏覽器無法創建對象。安全問題,容易給惡意程式隨意讀寫客戶的數據,一般不開放這個功能,改改註冊表,強行開通吧。
  2. 讀不到二進位數據。在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就固定轉化為1E80AC……

只是文件複製的話,持續沿用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用的是CP437字元集,直接把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>

後記

ISO-8859之外,還有許多字元集可使用,只要找到衝突編碼並轉換處理即可;

如果要js動態生成文件供瀏覽器下載,現代瀏覽器用blobcreateObjectURL輕鬆搞定;

在分離FileReader一段代碼至子函數時,對非同步操作的處理還鬧過小問題,Promise的邏輯還真是有些不適合本中老年;

IE8?不想玩了。

奇怪地是,再過了幾天,問new bing本文類似的問題,它拒絕給出示例代碼,說它不會,說它沒有記憶,說IE8沒法處理這個讀取本地二進位文件的問題……

本文來自博客園,作者:supervisor,轉載請註明原文鏈接:https://www.cnblogs.com/repus/p/17260978.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 保障資料庫的測試質量可以從以下幾個方面進行: (1)設計合理的測試用例:需要設計合理、全面、準確的測試用例,覆蓋資料庫的各種功能和場景,包括常規操作、異常操作、性能測試、安全測試等。 (2)自動化測試:可以採用自動化測試的方式,提高測試的效率和準確性,同時可以快速發現和解決問題。 (3)定期回歸測試 ...
  • 保障ETL過程的數據正確性可以從以下幾個方面考慮: 數據源的質量:ETL過程的數據質量取決於數據源的質量,因此需要對數據源進行充分的驗證和清洗,確保數據的準確性、完整性和一致性。 數據轉換的準確性:在ETL過程中,數據轉換是非常重要的一步,需要確保數據轉換的準確性和正確性。可以採用數據驗證、數據重覆 ...
  • 其實,Redis 的每種對象都有對象結構與對應編碼的數據結構組合而成,進階 Redis 就需要從它的對象機制開始。 ...
  • 事先申明:所有android 類型的學習記錄全部基於《第一行代碼 Android》第三版,在此感謝郭霖老師的書籍幫助。 1.手動創建Activity 在Project類型目錄中尋找到 項目/app/src/main/java/com.example.activitytest 在 com.exampl ...
  • 【導讀】 日常運營過程中,消息推送是App觸達用戶的常用手段,無論是新功能的通知,還是活動的提醒,都可以通過推送告知用戶。千人千面的個性化推送,對於提升用戶粘性、用戶轉化等指標都具有明顯正向效果。越來越多的應用選擇華為Push用戶增長服務作為拉新、促活的首選渠道,他們選擇的理由是什麼?他們又是如何持 ...
  • 我為什麼推薦Nuxt3? 大家好,我今天想和你們分享一個非常棒的前端框架——Nuxt3。自從我接觸了Nuxt3,我發現它在前端開發領域具有很多優點。我想逐一向你們介紹Nuxt3的優勢,並向大家推薦一些學習資源。 Nuxt3的優點 1、基於Vue3: Nuxt3是基於Vue.js 3開發的,Vue.j ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 今天給大家帶來的是Vue 3 中的極致防抖/節流(含常見方式防抖/節流)這篇文章,文章中不僅會講述原來使用的防抖或節流方式,還會帶來新的一種封裝方式,使用起來更簡單、更清晰。 前言 在前端的開發過程中,在涉及到與用戶交互的過程中是基本上都 ...
  • JSS 是什麼 簡單來說,一句話概括CSS in JS (JSS),就是"行內樣式"(inline style)和"行內腳本"(inline script)。 因為,自從React出現以後,基於組件化的要求,強制把HTML、CSS、JavaScript捆綁在一起,在同一個文件裡面,封裝了結構、樣式、 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...