|
本帖最后由 xingpengwei 于 2017-4-10 19:03 编辑
生物信息涉及很多序列文本的处理,例如fasta格式的文件,特别涉及不同平台间传递处理文本时,文末的回车换行符(Carriage-Return Line-Feed 回车换行,CRLF的意思就是回车(CR, ASCII 13, \r) 换行(LF, ASCII 10, \n))容易引起一些问题。
在Windows中:
'\r' 回车,回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖;
'\n' 换行,换到当前位置的下一行,而不会回到行首;
Unix系统里:
每行结尾只有“<换行>”,即"\n";Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;
Mac系统里:
每行结尾是“<回车>”,即"\r";
文本显示一般都不是大问题,无非Unix的文本用普通的windows的notepad会连成一行。
主要编程中一定要注意,一般涉及size之类的函数或者处理fasta的title获取label位置时,即使是同一个开发环境下(例如pycharm)不同平台会出现差异。那最近处理序列用到的C++的getline函数举例:
Mac系统下传过来的文本,在Unix系统下使用getline函数得到的line末尾可能会多出\r,size()函数也会多1,所以为了应该各种情况就得分类处理或者避免使用size之类的函数。
例如处理title获取label时,>124|0,java使用split,c++没有split则可以选择使用find获取‘|’的位置或判断后一位是不是0来判断
当处理序列行时,则需要分类处理,检查行末是否带有\r之类的字符。
对于c++可以写一个函数统一处理(见:Getting std :: ifstream to handle LF, CR, and CRLF?):
- std::istream& safeGetline(std::istream& is, std::string& t)
- {
- t.clear();
- // The characters in the stream are read one-by-one using a std::streambuf.
- // That is faster than reading them one-by-one using the std::istream.
- // Code that uses streambuf this way must be guarded by a sentry object.
- // The sentry object performs various tasks,
- // such as thread synchronization and updating the stream state.
- std::istream::sentry se(is, true);
- std::streambuf* sb = is.rdbuf();
- for(;;) {
- int c = sb->sbumpc();
- switch (c) {
- case '\n':
- return is;
- case '\r':
- if(sb->sgetc() == '\n')
- sb->sbumpc();
- return is;
- case EOF:
- // Also handle the case when the last line has no line ending
- if(t.empty())
- is.setstate(std::ios::eofbit);
- return is;
- default:
- t += (char)c;
- }
- }
- }
复制代码
其他语言也要注意,之前用python也出现过这类问题,一旦程序出问题,推荐debug查看line,log输出有时可能发现不了。
|
|