2014-11-05 46 views
0

我已經在node.js上編寫了一個簡單的TCP服務器來將一些數據發送到Chrome應用程序。在Chrome應用程序,當我得到的數據,我將其轉換成使用下面的函數字符串,我得到一個異常「Uint16Array的字節長度應爲2多」如何將arraybuffer轉換爲字符串

String.fromCharCode.apply(null, new Uint16Array(buffer)) 

我找不到任何有關可能導致此問題的信息以及如何解決此問題。任何指針都非常感謝。

下面是將數據發送到客戶端的node.js服務器代碼:

socket.on('data', function(data) { 

    console.log('DATA ' + socket.remoteAddress + ': ' + data); 
    // Write the data back to the socket, 
    // the client will receive it as data from the server 
    var r= socket.write('from server\r\n'); 

}); 

下面是鍍鉻的應用程序的代碼:

chrome.sockets.tcp.onReceive.addListener(function (info) { 
      console.log('onListener registered'); 
      if (info.socketId != socketid) 
       return; 
      else { 
       try { 

        data = ab2str(info.data); 
        console.log(data); 
       } 
       catch (e) { 
        console.log(e); 
       } 

      } 
      // info.data is an arrayBuffer. 
     }); 

function ab2str(buf) { 
    return String.fromCharCode.apply(null, new Uint16Array(buf)); 
} 
+0

可以顯示更多的你是如何得到緩衝? – Victory 2014-11-05 10:30:04

+0

一般來說,[這個問題](https://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers)是規範的。不過,我不會去dupehammer。 – Xan 2016-07-11 12:28:27

回答

6

你可能會看到這個問題,因爲您的應用程序在套接字上收到了奇數個字節,但是您試圖創建一個2字節寬度的數組(因爲這適合於​​)

如果您的應用程序接收通過網絡(5個字節)的字符串"Hello",那麼你可以強制轉換爲Uint8Array,它看起來就像這樣:

Item:  0 1 2 3 4 
Char:  H e l l o 
Uint8 Value: 72 101 108 108 111 

它轉換成一​​,但會盡量做到這個:

Item 0  1  2 
Chars He ll o? 
IntVal 25928 27756 ????? 

沒有第六個字節的工作,它不能構造數組,所以你會得到一個異常。

對數據使用​​只有在您期待套接字上的UCS-2字符串數據時纔有意義。如果您收到的是純ASCII數據,那麼您希望將其轉換爲Uint8Array,並將String.fromCharCode映射到該數據上。如果是其他的東西,比如UTF-8,那麼你將不得不做一些其他的轉換。

不管怎樣,套接字層始終可以免費發送任何長度的數據塊。您的應用必須處理奇數尺寸,並保存您無法處理的剩餘部分,以便您在接收到下一個數據塊時使用它。

+0

而解決方案將是...? – CesarD 2016-06-08 21:28:50

+0

它取決於應用程序 - 您可能希望使用Uint8Array,或者像我在最後一段中所述,緩衝任何尾隨字節,然後在獲取下一個數據包時將其用作第一個字節。 – 2016-06-09 03:44:54

+0

我的問題是我有一個返回錯誤的arraybuffer響應類型,但錯誤中的文本的一部分包含帶有重音符的字符,並且它們被解碼爲垃圾,幾乎不可讀的字符。我試圖用Uint16Array解碼它,像OP一樣,但得到了同樣的錯誤。 我最終找到了這個:https://gist.github.com/boushley/5471599,我能夠正確解碼字符串,而無需使用Uint16Array。 – CesarD 2016-06-09 14:16:10

1

的老種,晚,但也許使用該功能(original source)效果更好(它的工作對我來說解碼arraybuffer串不留一些特殊的字符作爲垃圾總量):

function decodeUtf8(arrayBuffer) { 
    var result = ""; 
    var i = 0; 
    var c = 0; 
    var c1 = 0; 
    var c2 = 0; 

    var data = new Uint8Array(arrayBuffer); 

    // If we have a BOM skip it 
    if (data.length >= 3 && data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) { 
    i = 3; 
    } 

    while (i < data.length) { 
    c = data[i]; 

    if (c < 128) { 
     result += String.fromCharCode(c); 
     i++; 
    } else if (c > 191 && c < 224) { 
     if(i+1 >= data.length) { 
     throw "UTF-8 Decode failed. Two byte character was truncated."; 
     } 
     c2 = data[i+1]; 
     result += String.fromCharCode(((c&31)<<6) | (c2&63)); 
     i += 2; 
    } else { 
     if (i+2 >= data.length) { 
     throw "UTF-8 Decode failed. Multi byte character was truncated."; 
     } 
     c2 = data[i+1]; 
     c3 = data[i+2]; 
     result += String.fromCharCode(((c&15)<<12) | ((c2&63)<<6) | (c3&63)); 
     i += 3; 
    } 
    } 
    return result; 
} 
0

有一個異步使用BlobFileReader的方式。

您可以指定任何有效的編碼。

function arrayBufferToString(buffer, encoding, callback) { 
    var blob = new Blob([buffer],{type:'text/plain'}); 
    var reader = new FileReader(); 
    reader.onload = function(evt){callback(evt.target.result);}; 
    reader.readAsText(blob, encoding); 
} 

//example: 
var buf = new Uint8Array([65,66,67]); 
arrayBufferToString(buf, 'UTF-8', console.log.bind(console)); //"ABC" 
+0

您可能希望查看['TextDecoder' API](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)以獲取同步的方式。 – Xan 2016-07-11 12:27:21

+0

謝謝。 [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)非常好,但只支持firefox和chrome。 IE和Safari需要大墊片。 – cuixiping 2016-07-14 07:19:57

+0

問題在於Chrome應用程序,因此運行時顯式爲Chrome。 – Xan 2016-07-14 07:56:43

2

現代(鉻38+)的方法來做到這將是,假定編碼是UTF-8:

var decoder = new TextDecoder("utf-8"); 

function ab2str(buf) { 
    return decoder.decode(new Uint8Array(buf)); 
} 

這使用TextDecoder API;請參閱documentation瞭解更多選項,例如不同的編碼。

參見:Easier ArrayBuffer<->String conversion with the Encoding API @ Google Developers

+0

對於不支持此API的其他瀏覽器,有[TextDecoder shim/polyfill](https://github.com/inexorabletash/text-encoding)。 – cuixiping 2016-07-15 16:53:56