LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
12
返回列表 发新帖
楼主: wjping119

两位两位数据变四位的问题

[复制链接]
发表于 2009-5-21 22:58:28 | 显示全部楼层
不明白为什么要用文本文件
二进制方式保存,二进制方式打开,处理,那样速度不是更快吗
用文本方式保存,处理,不但浪费硬盘,处理时还要作额外转换,不是浪费CPU吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-22 08:29:52 | 显示全部楼层
采集下的数据是比如xxx.dat,这个文件就是十六进制的,但是我不晓得如何在matlab里直接处理这个dat文件,但是知道matlab能读取txt,于是txt中的十六进制是我用UE打开后复制出来的~~
回复 支持 反对

使用道具 举报

发表于 2009-5-22 11:18:27 | 显示全部楼层
建议还是google搜索下吧,关键字: matlab 二进制文件
转成文本是在逃避问题,还会产生新的问题
要处理大量数据,这样转换岂不是画蛇添足

ps:你的xxx.dat应该称为二进制数据文件,是UE打开二进制文件以十六进制方式显示出来
在硬盘上,内存里,全都是二进制数据,1个字节(byte)有8个二进制位(bit)
比如某个文件有2字节,在硬盘上的实际数据是1111111100000000
UE以二进制方式打开它就显示成FF 00
你再复制出来保存为txt,就成了ASCII编码的文件
以十六进制方式显示这个txt就会像这样: 46 46 20 30  30
F 的ASCII码是70,十六进制表示就是46
空格 的ASCII码是32,十六进制表示就是20
0 的ASCII码是48,十六进制表示就是30
本来很简单的FF00被转换成了4646203030,这不是多余吗,txt纯文本并不是想像中那么“纯”
数据少还没什么,数据很多的话,这样冗余的数据又吃内存,又吃CPU,难怪matlab要"死翘翘"
二进制数据文件还是应该老老实实以二进制方式打开处理
文本编辑器以十六进制来显示,编辑二进制文件,用于作少量的手动修改还行,大量的转换成十六进制文本文件,没有太大意义
回复 支持 反对

使用道具 举报

发表于 2009-5-23 23:01:09 | 显示全部楼层
写了个简单的shell脚本来把你的txt转换回二进制数据文件,发现运行超慢,200k的txt就要6s,又用c来写了个程序,发现时间消耗不是一个数量级的...
w10.txt是10份原来的wwww.txt连接成,测试下时间消耗
文本已经由dos格式转成unix格式,去掉了CR
  1. $ ls -n w10.txt
  2. -rw-r--r-- 1 1000 1000 1927660 05-23 19:05 w10.txt
  3. $ time cpath/txt2data w10.txt 10.dat
  4. real    0m0.175s
  5. user    0m0.148s
  6. sys 0m0.024s
  7. $ time shellpath/txt2data w10.txt 10.dat2
  8. real    1m1.204s
  9. user    0m43.419s
  10. sys 0m17.089s
  11. $ diff 10.dat 10.dat2   #没有输出,文件一致
复制代码
[color="Red"]shell脚本要61s,c程序只要0.175s,汗死...
不知道shell用什么方法可以处理更快

shell脚本
  1. #!/bin/bash
  2. [ $# -eq 2 ] || exec echo 'Usage:   txt2data input.txt output.dat'
  3. if [ -f "$1" ]; then
  4.     txt_list=$(cat $1)
  5. else
  6.     exec echo File "$1" not exist!
  7. fi
  8. data=
  9. for hex_txt in $txt_list; do
  10.     printf "\x$hex_txt" >> "$2"
  11. done
复制代码

c程序
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. main(int argc,char *argv[])
  4. {
  5.     int asc[2],data,i;
  6.     FILE *ascstream,*outstream;
  7.     if ( argc != 3 )
  8.     {
  9.         printf("Usage: txt2data input.txt ouput.dat\n");
  10.         exit(1);
  11.     }
  12.     if((ascstream=fopen(argv[1],"rt"))==NULL)
  13.     /*只读文本模式打开输入文件*/
  14.     {
  15.         printf("Can not open input file: %s\n",argv[1]);
  16.         exit(2);
  17.     }
  18.     if((outstream=fopen(argv[2],"wb"))==NULL)
  19.     /*只写模式创建二进制输出文件,重名则覆盖已有文件*/
  20.     {
  21.         printf("Can not create file: %s\n",argv[2]);
  22.         fclose(ascstream);
  23.         exit(2);
  24.     }
  25.     asc[0]=fgetc(ascstream);
  26.     while(asc[0] != EOF )
  27.     {
  28.         asc[1]=fgetc(ascstream);
  29.         for(i=0;i<=1;i++)
  30.         {
  31.             if (asc[i] >= 65)
  32.                 asc[i]=asc[i]-55;
  33.             else
  34.                 asc[i]=asc[i]-48;
  35.         }
  36.         data=asc[0]*16 + asc[1];
  37. //      fwrite(&data,sizeof(char),1,outstream);
  38.         fputc(data,outstream);
  39.         do
  40.             asc[0]=fgetc(ascstream);
  41.             /*忽略空格回车换行*/
  42.         while(asc[0]==0x20 || asc[0]==0x0a || asc[0]==0x0d);
  43.     }
  44.     while(fclose(outstream));
  45.     fclose(ascstream);
  46.     exit(0);
  47. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2009-5-29 11:55:40 | 显示全部楼层
写了个读取楼主的二进制数据文件并做转换的C程序

猜测楼主的dat数据格式是这样的:
文件开头FF0000是起始标志,接着是1024个2字节(16位)数据(一帧2048字节),然后EB90就是新帧开始的标志,接着XXXXXX三字节表示帧序号,接着一帧数据2048字节。。。。。。

简单测试下

首先,把楼主的txt文本转换成dat二进制数据文件
  1. $ ./txt2data wwww.txt f30.dat
  2. $ ls -n wwww.txt f30.dat
  3. -rw-r--r-- 1 1000 1000  62944 05-29 10:41 f30.dat
  4. -rw-r--r-- 1 1000 1000 196698 05-29 10:22 wwww.txt
复制代码

生成100M数据文件样本用来测试消耗时间
5w帧的数据文件,按楼主的数据格式,实际数据就是那30帧不断重复(不足一帧的数据忽略),帧序一直递增
  1. $ time ./dataread c50000 f30.dat f5w.dat

  2. Frame 0x000000 To 0x00001e        Only 675 data in frame 0x00001e, ignore!
  3. ..................................................
  4. Prev message repeat 1666 total
  5. Frame 0x000000 To 0x000013       

  6. Total output: 50000 frames.

  7. real        0m2.296s
  8. user        0m0.308s
  9. sys        0m1.840s
  10. $ ls -n f5w.dat
  11. -rw-r--r-- 1 1000 1000 102649998 05-29 10:41 f5w.dat
复制代码

输出纯粹的帧二进制数据,不留标志,小端
  1. $ time ./dataread f5w.dat out.dat
  2. ..................................................
  3. Frame 0x000000 To 0x00c34f       

  4. Total output: 50000 frames.

  5. real        0m3.017s
  6. user        0m1.144s
  7. sys        0m1.716s
  8. $ ls -n out.dat
  9. -rw-r--r-- 1 1000 1000 102400000 05-29 10:52 out.dat
复制代码

输出楼主原来想要的十六进制文本文件,只有帧数据,不留标志
  1. $ time ./dataread t f5w.dat out.txt
  2. ..................................................
  3. Frame 0x000000 To 0x00c34f       

  4. Total output: 50000 frames.

  5. real        0m35.097s
  6. user        0m30.022s
  7. sys        0m4.032s
  8. $ ls -n out.txt
  9. -rw-r--r-- 1 1000 1000 268800000 05-29 10:54 out.txt
  10. $ head -n5 out.txt
  11. 8118 8117 8193 8147 8187 81E7 81C6 81ED
  12. 8236 81D5 81E6 827E 8287 828A 828B 8289
  13. 827A 8286 82AA 82BE 82B3 82A1 82B3 8257
  14. 8276 826F 8234 8207 82C4 8267 81CA 81EA
  15. 8170 81A1 816D 813B 8153 8103 80F1 8099
复制代码

再把txt转换回dat,大小和前面的out.dat一样,只是每两字节顺序相反
  1. $ time ./txt2data out.txt out.dat1

  2. real        0m29.446s
  3. user        0m22.853s
  4. sys        0m3.004s
  5. liu@debian:c$ ls -n out.dat1
  6. -rw-r--r-- 1 1000 1000 102400000 05-29 11:55 out.dat1
复制代码

楼主的dat数据文件应该是大端的,x86体系是小端,直接fread得到的字节序是反的(不明白的话google搜索下:endian 大端 小端)
用c参数时不作转换,输出大端,保持原貌,仅设置帧序递增,指定生成5w帧数据耗时2.3s
不带参数时,输出二进制数据文件,转换成小端,处理5w帧数据耗时3s
用t参数生成十六进制txt文件,处理5w帧数据耗时35s
用txt2data转换回二进制数据文件消耗29.4s
程序越写越大,还有些其它选项,还没仔细测试,需要的话可以发上来

为了处理数据文件而转换成txt确实是不值得的
C语言用fread函数读二进制数据文件,matlab不是也有fread函数可以读二进制数据文件吗,我没装过matlab,但是搜索下就知道了,matlab也是一种高级语言,处理大量数据应该比C更方便。

写这个程序仅供测试参考,没必要真的用它来转换大量数据成txt文本。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表