我有一个ERP系统,它以RTF格式存储文本,我试图从中提取纯文本。
我通过Google进行了搜索,发现了像this one这样的解决方案以及其他一些使用REGEX替换的解决方案,但似乎都没有。我总是得到NULL
或}}}
或完全错误。
这是我试过的REGEX:
$matches = array('/\{\\\\(.+?)\}/','/\\\\(.+?)\b/');
$row['text'] = preg_replace($matches,'',$row['text']);
然而它返回:}}}
这是我的RTF数据:
{\rtf1\deff0{\fonttbl{\f0 Calibri;}{\f1 Arial;}}{\colortbl ;\red0\green0\blue255 ;}{\*\defchp \fs22}{\*\listoverridetable}{\stylesheet {\ql\fs22 Normal;}{\*\cs1\f1\fs20 Default Paragraph Font;}{\*\cs2\sbasedon1\f1\fs20 Line Number;}{\*\cs3\ul\fs22\cf1 Hyperlink;}{\*\ts4\tsrowd\fs22\ql\trautofit1\tscellpaddfl3\tscellpaddl108\tscellpaddfr3\tscellpaddr108\tsvertalt\cltxlrtb Normal Table;}{\*\ts5\tsrowd\sbasedon4\fs22\ql\trbrdrt\brdrs\brdrw10\trbrdrl\brdrs\brdrw10\trbrdrb\brdrs\brdrw10\trbrdrr\brdrs\brdrw10\trbrdrh\brdrs\brdrw10\trbrdrv\brdrs\brdrw10\trautofit1\tscellpaddfl3\tscellpaddl108\tscellpaddfr3\tscellpaddr108\tsvertalt\cltxlrtb Table Simple 1;}}\nouicompat\splytwnine\htmautsp\sectd\pard\plain\ql{\f1\fs20\cf0 Migration Fileserverdaten innerhalb derselben oder einer vertrauten Dom\u228\'e4ne}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Anpassung der Laufwerksfreigaben}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Freigabenerstellung wie Bestand (weitere Absprachen hierzu m\u246\'f6glich)}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Hostname(n) Quellsystem(e):}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Hostname Zielsystem:}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Bekanntes Datenvolumen:}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Clientseitige Nacharbeiten aufgrund fest vergebener Einstellungen}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 erfolgen nach Aufwand oder durch den Auftraggeber.}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Es wird im Besonderen darauf hingewiesen, da\u223\'df Datei- und Ornderberechtigungen 1:1 beibehalten werden. Die Neuvergabe jedweder Datei- oder Ordnerberechtigung kann nach Aufwand und Anweisung des Auftraggebers durchgef\u252\'fchrt werden.}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Voraussetzungen zur Zusatzaufwandsfreien Durchf\u252\'fchrung:}\f1\fs20\par\pard\plain\ql{\f1\fs20\cf0 Gigabit Switching zwischen allen Quell- und Zielsystemen, Vollzugriff auf den zu migrierenden Datenbestand}\f1\fs20\par\pard\plain\ql\f1\fs20\par}
编辑2019:对于所有发现这个问题的人,我使用这个单班项目,因为4年没有问题 https://github.com/henck/rtf-html-php/blob/master/rtf-html-php.php
答案 0 :(得分:1)
您可以在此处找到Rtf文本提取器:
以下是如何使用它的示例:
include ( 'path/to/RtfTexter.phpclass' ) ;
$doc = new RtfTexter ( 'sample.rtf' ) ;
echo $doc -> AsString ( ) ; // Echo text contents to stdout
$doc -> SaveTo ( 'sample.txt' ) ; // Save text contents to file 'sample.txt'
答案 1 :(得分:1)
我正在为这个问题发布一个通用解决方案,让其他人跳到这里。
public static function converToPlain($text){
$text = preg_replace('"{\*?\\\\.+(;})|\\s?\\\[A-Za-z0-9]+|\\s?{\\s?\\\[A-Za-z0-9‹]+\\s?|\\s?}\\s?"', '', $text);
return $text;
}
答案 2 :(得分:0)
经过一些脑力力量后,我找到了一个解决方案:
试试这个正则表达式:
"{\*?\\.+(;})|\s?\\[A-Za-z0-9]+|\s?{\s?\\[A-Za-z0-9]+\s?|\s?}\s?"
表示用
替换代码$count = null;
$matches = array('"{\*?\\.+(;})|\s?\\[A-Za-z0-9]+|\s?{\s?\\[A-Za-z0-9]+\s?|\s?}\s?"');
$row['text'] = preg_replace($matches,'',$row['text'], -1, $count);
答案 3 :(得分:0)
大家好我写这段代码读取rtf文件纯文本此代码100%
那里的PHP代码:
$text = file_get_contents('testfile.rtf');
if (!strlen($text)) {
echo "bad file";
exit();
}
// we'll try to fix up the parts of the rtf as best we can
// clean up the file a little to simplify parsing
$text=str_replace("\r",' ',$text); // returns
$text=str_replace("\n",' ',$text); // new lines
$text=str_replace(' ',' ',$text); // double spaces
$text=str_replace(' ',' ',$text); // double spaces
$text=str_replace(' ',' ',$text); // double spaces
$text=str_replace(' ',' ',$text); // double spaces
$text=str_replace('} {','}{',$text); // embedded spaces
// skip over the heading stuff
$j=strpos($text,'{',1); // skip ahead to the first part of the header
$loc=1;
$t="";
$ansa="";
$len=strlen($text);
getpgraph(); // skip by the first paragrap
while($j<$len) {
$c=substr($text,$j,1);
if ($c=="\\") {
// have a tag
$tag=gettag();
if (strlen($tag)>0) {
// process known tags
switch ($tag) {
case 'par':
$ansa.="\r\n";
break;
// ad a list of common tags
// parameter tags
case 'spriority1':
case 'fprq2':
case 'author':
case 'operator':
case 'sqformat':
case 'company':
case 'xmlns1':
case 'wgrffmtfilter':
case 'pnhang':
case 'themedata':
case 'colorschememapping':
$tt=gettag();
break;
case '*':
case 'info':
case 'stylesheet':
// gets to end of paragraph
$j--;
getpgraph();
default:
// ignore the tag
}
}
} else {
$ansa.=$c;
}
$j++;
}
$ansa=str_replace('{','',$ansa);
$ansa=str_replace('}','',$ansa);
echo "<pre>$ansa</pre>";
function getpgraph() {
// if the first char after a tag is { then throw out the entire paragraph
// this has to be nested
global $text;
global $j;
global $len;
$nest=0;
while(true) {
$j++;
if ($j>=$len) break;
if (substr($text,$j,1)=='}') {
if ($nest==0) return;
$nest--;
}
if (substr($text,$j,1)=='{') {
$nest++;
}
}
return;
}
function gettag() {
// gets the text following the / character or gets the param if it there
global $text;
global $j;
global $len;
$tag='';
while(true) {
$j++;
if ($j>=$len) break;
$c=substr($text,$j,1);
if ($c==' ') break;
if ($c==';') break;
if ($c=='}') break;
if ($c=="\\") {
$j--;
break;
}
if ($c=="{") {
//getpgraph();
break;
}
if ((($c>='0')&&($c<='9'))||(($c>='a')&&($c<='z'))||(($c>='A')&&($c<='Z'))||$c=="'"||$c=="-"||$c=="*" ){
$tag=$tag.$c;
} else {
// end of tag
$j--;
break;
}
}
return $tag;
}
答案 4 :(得分:0)
我尝试了@Anurag Prashant的建议,但有时不起作用。例如,此rtf转换不正确:
{\rtf1\ansi\ansicpg1252\deff0\deflang1036{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
{\colortbl ;\red0\green0\blue0;}
{\*\generator Msftedit 5.41.15.1515;}\viewkind4\uc1\pard\cf1\f0\fs18 - test\cf0\par
}
这是一个看起来效果更好的php正则表达式:
/(\{.*\})|}|(\\\\(?!')\S+)/m
public static function converToPlain($text)
{
$text = preg_replace('/(\{.*\})|}|(\\\\(?!')\S+)/m', '', $text);
return $text;
}
答案 5 :(得分:0)
我知道这是一个老问题,但我最近不得不做类似的事情,这个页面上的各种答案都有很大帮助。然而,它们都没有完全满足我的需求,所以我不得不将其中的几个组合起来,然后添加一些我自己的。
代码如下:
我的代码只处理与我相关的特殊字符的一个子集,但我包含了一个指向列出所有这些字符的页面的链接。
提取 PNG 图像,然后在文本末尾重新插入为 HTML 图像,有点像电子邮件附件。它并不完美,但足以满足我的需求。另外,我不知道其他图像格式是如何工作的,但我怀疑我的代码可以很容易地适应 JPG 等。
$plain = $rtfSource;
// we have to remove all line breaks, otherwise
// the RTF>TXT regexp below doesn't work correctly.
$plain = preg_replace( '/\r|\n/', '', $plain);
// extract the images
// example: {\pict\pngblip\picw1166\pich190\picwgoal8071\pichgoal1315 89504e470d0a1a0a00...454e44ae426082}
// the hexadecimal code for the image starts after the
// whitespace and runs until the first } that we encounter.
// then it has to be converted into base64.
$imgHtml = '';
$imgMatches = array();
$imgRegex = '/{\\\\pict\\\\pngblip\\\\[a-z0-9]+\\\\[a-z0-9]+\\\\[a-z0-9]+\\\\[a-z0-9]+ ([a-z0-9]+)}/';
preg_match_all($imgRegex, $plain, $imgMatches);
if (count($imgMatches[1])) {
for ($i=0; $i < count($imgMatches[1]); $i++) {
$imgHtml .= '<img src="data:image/png;base64, ' . base64_encode(pack('H*', $imgMatches[1][$i])) . '">';
}
}
// remove those images (or else their hex code is still displayed as text)
$plain = preg_replace($imgRegex, '', $plain);
// RTF>TXT (https://stackoverflow.com/a/42525858/357546)
$plain = preg_replace('"{\*?\\\\.+(;})|\\s?\\\[A-Za-z0-9]+|\\s?{\\s?\\\[A-Za-z0-9‹]+\\s?|\\s?}\\s?"', '', $plain);
// special characters; for a full list, see:
// https://www.oreilly.com/library/view/rtf-pocket-guide/9781449302047/ch04.html
$plain = str_replace("\'3f", '?', $plain);
$plain = str_replace("\'80", '€', $plain);
$plain = str_replace("\'a8", '¨', $plain);
$plain = str_replace("\'ab", '«', $plain);
$plain = str_replace("\'ae", '®', $plain);
$plain = str_replace("\'b0", '°', $plain);
$plain = str_replace("\'bb", '»', $plain);
$plain = str_replace("\'c4", 'Ä', $plain);
$plain = str_replace("\'c9", 'É', $plain);
$plain = str_replace("\'d6", 'Ö', $plain);
$plain = str_replace("\'dc", 'Ü', $plain);
$plain = str_replace("\'df", 'ß', $plain);
$plain = str_replace("\'e0", 'à', $plain);
$plain = str_replace("\'e2", 'â', $plain);
$plain = str_replace("\'e4", 'ä', $plain);
$plain = str_replace("\'e7", 'ç', $plain);
$plain = str_replace("\'e8", 'è', $plain);
$plain = str_replace("\'e9", 'é', $plain);
$plain = str_replace("\'ea", 'ê', $plain);
$plain = str_replace("\'eb", 'ë', $plain);
$plain = str_replace("\'ee", 'î', $plain);
$plain = str_replace("\'f4", 'ô', $plain);
$plain = str_replace("\'f6", 'ö', $plain);
$plain = str_replace("\'f8", 'ø', $plain);
$plain = str_replace("\'fb", 'û', $plain);
$plain = str_replace("\'fc", 'ü', $plain);
// a bit of cleaning
$plain = trim($plain);
$plain = preg_replace('/^-0 /', '', $plain);
$plain .= $imgHtml;
echo $plain;