如何拆分(包含特定二进制值的二进制包含字符串?

时间:2018-04-03 00:03:25

标签: javascript split binary

概述:   我在网页中构建了一个Javascript工具。除了加载该页面外,该工具将在没有服务器通信的情况下运行。用户将选择包含多个二进制记录的本地文件,每个记录具有x< F0起始字节和x' F0结束字节。其间的数据限制在x&00; 00 - x' 7F,包括:

  • 位图
  • 1字节数字
  • 2字节数字,低位字节优先
  • 一小部分ASCII字符

记录长度不同,使用不同的格式。 [它是一组MIDI Sysex消息,可能不相关]。 通过reader.readAsArrayBuffer读取本地文件,然后进行处理:

var contents = event.target.result;
var bytes = new Uint8Array(contents);
var rawAccum = '';
for (x = 0; x < bytes.length; x++) { 
  rawAccum += bytes[x];
}
var records = rawAccum.split(/\xF0/g);

我希望将字符串拆分为其组成记录的数组,删除进程中的x&#39; F0起始字节。 它实际上做得很少。 records.length为1,records [0]包含整个输入流。

[实际的分割代码是:var records = rawAccum.split(/ \ xF0 \ x00 \ x00 \ x26 \ x02 / g);应从每条记录的开头删除几个相同的字节。当这次失败时,我尝试了上面的缩写版本,结果相同(非)。]

我已经查看了有关拆分的文档(以及正则表达式引用中对\ xXX的几种解释。显然,某些内容不能像我推断的那样起作用。我使用JavaScript的经验很少且是零星的。

如何在出现特定二进制字节时拆分一串二进制数据?

1 个答案:

答案 0 :(得分:0)

拆分似乎工作正常:

var rawAccum = "\xf0a\xf0b\xf0c\xf0"
console.log( rawAccum.length);       // 7
var records = rawAccum.split(/\xF0/g);
console.log(records);                // "", "a", "b", "c", ""

但是将数组缓冲区转换为字符串看起来很可疑。尝试将无符号字节值转换为字符串,然后将其附加到rawAccum

for (x = 0; x < bytes.length; x++) { 
    rawAccum += String.fromCharCode( bytes[x]);
}

<小时/> 数据转换评论后更新

文件读取器将文件读入内存中的数组缓冲区,但JavaScript不能直接访问数组缓冲区。您可以从缓冲区创建和初始化类型化数组(例如,使用文章中的Uint8Array构造函数),或使用DataView object访问缓冲区中的字节。 DataView对象的方法可以将指定位置的字节序列转换为不同类型的整数,例如Midi sysex记录中的16位整数。

JavaScript字符串使用16位值的序列来保存字符,其中每个字符使用一个或两个使用UTF-16字符编码编码的16位值。 8位字符仅使用单个16位值的低8位来存储其Unicode代码点。

通过将缓冲区中的每个字节值存储在16位字符的低位中并将其附加到现有字符串,可以将八位位组值的数组缓冲区转换为“二进制字符串”。这就是帖子试图做的事情。但是在JavaScript字符串中(以及字符串长度为1的单个字符)不是整数的子集,并且有自己的数据类型,“string”。

因此,要将无符号8位数转换为类型为“string”的JavaScript 16位字符,请使用全局fromCharCode对象的String静态方法,如

rawAccum += String.fromCharCode( bytes[x]);

调用String.fromCharCode也是如何将MIDI数据中的ASCII字符代码转换为JavaScript中的字符。

要将从8位值派生的二进制字符串字符转换回数字,请对字符串值使用String实例方法charCodeAt并提供字符位置:

var byteValue = "\xf0".charCodeAt(0);

返回数字0xf0或250十进制。

如果在字符串中附加一个数字,就像在问题中一样,该数字首先隐式转换为其值的十进制字符串表示形式:

"" + 0xf0 + 66 // becomes the string "24066"

<小时/> 请注意,可以使用从其创建的Uint8Array检查数组缓冲区,使用缓冲区的slice方法将其切片,并使用数据视图从缓冲区中提取各种类型的整数。请查看创建二进制字符串是否仍然是提取和解释Midi记录内容的最佳方式。