- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用 socket.recv() 通过套接字(蓝牙)从设备接收二进制数据。
我考虑过在列表或字节数组中进行缓冲,直到收到足够的数据进行解码和操作。也就是说,直到我收到开始标志和停止标志(字节)。
但是,设备正在应用“八位字节填充”。也就是说,以下两个字节的每次出现都应替换为单个字节,如下所示:
dic = { '\xFE\xDC' : '\xFC' , '\xFE\xDD' : '\xFD' , '\xFE\xDE' : '\xFE'}
此外,在发送数据时,应该应用反向。例如,一个字节 0xFC -> 产生两个字节 0xFE、0xDC。
真正发生的是,当填充(发送数据)时,如果检测到 0xFC、0xFD、0xFE 之一,则在字节之前添加 0xFE,该字节本身是异或 0x20。在取消填充(接收数据)时,0XFE 被丢弃,随后的字节被异或 0x20。
说我是 Python 的新手一点都不为过。我昨天开始编码,启动并运行了一个界面。然而,这有点棘手。
我知道我可以将数据放入字符串中并进行替换。但是把二进制数据打包成字符串,替换然后解包解码好像效率有点低。
我还可以查看传入数据并在看到 0xFE 标志时采取行动。如果有一种方法可以填充/取消填充列表、字节数组或其他任何东西,那就太好了。
替换列表或 bytearray 中的单个字节似乎并不难,但是用两个替换一个或其他方式......?
非常感谢任何帮助。
(顺便说一句,这是 Python 2.7。)
最佳答案
您需要包装字节流并转义特定值。此外,还需要另一种方法:取消转义控制代码并获取原始有效负载。您正在使用套接字。套接字命令使用字符串参数。在 Python 中,每个字符串基本上都是 char*
数组的包装器。
它是一个字符串,我们想用其他值替换特定值。那么实现这一目标的最简单方法是什么?
def unstuff(self, s):
return s.replace('\xFE\xDC', '\xFC').replace('\xFE\xDD', '\xFE').replace('\xFE\xDE', '\xFE')
def stuff(self, s):
return s.replace('\xFC', '\xFE\xDC').replace('\xFD', '\xFE\xDD').replace('\xFE', '\xFE\xDE')
好像不好。每次替换调用都会创建一个新的字符串副本。
一个非常 pythonic 的方法是为这个特定问题定义一个迭代器:定义迭代器以将输入数据转换为所需的输出。
def unstuff(data):
i = iter(data)
dic = {'\xDC' : '\xFC', '\xDD' : '\xFD', '\xFE' : '\xDE'}
while True:
d = i.next() # throws StopIteration on the end
if d == '\xFE':
d2 = i.next()
if d2 in dic:
yield dic[d2]
else:
yield '\xFE'
yield d2
else:
yield d
def stuff(data):
i = iter(data)
dic = { '\xFC' : '\xDC', '\xFD' : '\xDD', '\xFE' : '\xDE' }
while True:
d = i.next() # throws StopIteration on the end
if d in dic:
yield '\xFE'
yield dic[d]
else:
yield d
def main():
s = 'hello\xFE\xDCWorld'
unstuffed = "".join(unstuff(s))
stuffed = "".join(stuff(unstuffed))
print s, unstuffed, stuffed
# also possible
for c in unstuff(s):
print ord(c)
if __name__ == '__main__':
main()
stuff()
和 unstuff()
需要一些可迭代的东西(列表、字符串、...)并返回 iterator-object .如果要打印
结果或将其传递给socket.send
,则需要将其转换回字符串(如"".join(所示) )
)。每个意外数据都以某种方式处理:0xFE 0x__
如果不匹配任何模式,将逐字返回。
另一种方法是使用 regular expressions .这是一个很大的话题,有时也是麻烦的根源,但我们可以保持简单:
import re
s = 'hello\xFE\xDCWorld' # our test-string
# read: FE DC or FE DD or FE DE
unstuff = re.compile('\xFE\xDC|\xFE\xDD|\xFE\xDE')
# read:
# - use this pattern to match against the string
# - replace what you have found (m.groups(0), whole match) with
# char(ord(match[1])^0x20)
unstuffed = unstuff.sub(lambda m: chr(ord(m.group(0)[1])^0x20), s)
# same thing, other way around
stuff = re.compile('\xFC|\xFD|\xFE')
stuffed = stuff.sub(lambda m: '\xFE' + chr(ord(m.group(0))^0x20), unstuffed)
print s, unstuffed, stuffed
如前所述,您必须在某处创建新字符串才能将其用于套接字。至少,这种方法不会像 s.replace(..).replace(..).replace(..)
那样创建不必要的字符串副本。您应该将模式 stuff
和 unstuff
保留在某个地方,因为构建这些对象的成本相对较高。
如果某些事情在 python 中会变慢,我们可能想使用 cpython 并将其实现为我们的 C 代码。基本上,我进行第一次运行,计算我有多少字节,分配一个新字符串并进行第二次运行。我不太习惯 python-c-extensions,所以我不想分享这段代码。它似乎有效,请参阅下一章
最重要的优化规则之一:比较!每个测试的基本设置:
generate random binary data as a string
while less_than_a_second:
unstuff(stuff(random_data))
count += 1
return time_needed / count
我知道,设置不是最佳的。但是我们应该得到一些可用的结果:
我们看到了什么? native 是最快的方法,但仅适用于非常小的字符串。这可能是因为 python 解释器:只需要一个函数调用而不是三个。但大多数时候微秒已经足够快了。在大约 500 字节之后,时间与原始方法几乎相同。在实现过程中一定有一些深奥的魔法在发生。与努力相比,迭代器和 RegExp 是 Not Acceptable 。
总结一下:使用天真的方法。很难得到更好的东西。另外:如果您只是猜测时间,您几乎总是错的。
关于python - 八位字节(字节)填充和取消填充,即用两个或 v.v 替换一个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13530087/
是否可以使用标准输入/标准输出在 bash 中压缩/解压缩字符串? 我试过了,但显然不支持它? hey=$(echo "hello world" | gzip -cf) echo $hey # ret
我的任务是让一个企业网站适用于 IE7,它必须“足够好”,因此我禁用了任何导致问题的花哨/非必要功能。 其中之一是正在使用的搜索栏,需要进行哪些搜索,我猜测幕后某个地方有某种 JavaScript 用
我有一个执行大量处理的小程序。您可以通过按回车键打印进度。 我实现它的方法是在主线程中完成处理,同时我有一个 pthread 不断循环 getchar() 以等待输入键。 问题是当我完成处理时。发生这
我完全理解 suspendCoroutine 与 suspendCancellableCoroutine 在我的示例中的工作方式。但我想知道为什么 println("I finished") (第 1
我是 QT 的新手。目前在我的项目中我实现了 QFileDialog . 在我的用例中:每当用户选择一个文本文件时,它都会执行 functionA .但是,我发现如果在文件对话框中单击取消,funct
我有代码,仅在用户选择“另存为”时运行。为此并获取我正在使用的文件的新名称 Application.GetSaveAsFilename功能。 我遇到的问题是类型不匹配,同时检查用户是否在他没有这样做时
我的 UILocalNotification 有问题。 我正在用我的方法安排通知。 - (void) sendNewNoteLocalReminder:(NSDate *)date alrt:(NS
祝你有美好的一天 我有一个网站,其中有很多“工具提示”。这些工具提示是在将鼠标悬停在文本的特定部分上时创建的。工具提示是一个 div block ,它显示在网站上所有其他内容的顶部,并且当光标从文本移
我遇到以下问题。每隔 2 秒,程序就会进入 if 语句。在这个 if 语句中,我想要一个计时器,它会在 15 秒后给我一条消息。计时器应延迟 1 秒运行。但是当我用计时器“等待”时,if 语句将再执行
基本上我有以下代码片段, (let [task (FutureTask. fn) thr (Thread. task)] (.start thr) ;;wait for signa
取消正在进行的 ASIHttpRequest 请求的正确位置在哪里?这就是我取消的方式,但是当我 时它继续崩溃在不让请求完成的情况下从一个 View Controller 转移到另一个 View Co
我在我的 winforms 应用程序中使用 BackgroundWorker 来执行另一个类中发生的长时间运行的任务(执行数据库操作)。由于所有工作都是在另一个类中完成的,因此取消并不那么简单。我在另
我正在使用 OneSignal 向我的用户显示通知。通知工作正常,但我注意到,如果我在通知栏中“滑动”取消通知,则通知将永远保留,这是一张显示应用程序图标上的通知的图像,我想在应用程序已打开: 我看到
正在运行的 AsyncTask 的 .cancel(boolean) 方法如何工作?这是文档: Attempts to cancel execution of this task. This atte
我注意到,当我激活约束时,我会立即在该行代码处收到一条警告,指出不能同时满足约束。 我假设布局是在“UI 更新周期”之类的稍后时间点计算的,而不是每次约束都被(取消)激活。因此,在(取消)激活约束的代
这是我创建线程的方式: readFromWebThread = [[NSThread alloc] initWithTarget:self selector:@selector(loadThread:
我目前正在尝试取消与我的数据模型中的对象关联的特定 UILocalNotifications。为此,每个数据对象都有一个唯一标识符,即 NSUUID。 创建 UILocalNotification:
当我提交并单击“确定”时,它会继续,但当我按“取消”时,它仍然会提交。我尝试使用此代码,但提交和取消按钮仍然执行相同的操作。 model.saveForm = function() { var
我有一个警报弹出窗口,当发生特定操作时会出现该弹出窗口。 5 秒后,使用 setTimeout() 隐藏警报弹出窗口。 我遇到的问题是,如果我多次触发弹出窗口,有时后续的弹出窗口会出现但立即消失。我相
我有一些 javascipt (jQuery),其中单击按钮时会淡入 #myDiv,然后使用超时函数在 5 秒后再次淡出。它工作正常,但如果用户在超时内的 fadeOut 函数运行之前再次单击该按钮,
我是一名优秀的程序员,十分优秀!