История изменений
Исправление praseodim, (текущая версия) :
Спасибо, интересная возможность, даже не знал, что w3m можно использовать.
Но все же w3m и существенно медленнее даже без mmap получается. А главное, не может слишком большой файл обработать. Например, если 11G подсунуть валится с ошибкой «Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS» Aborted
fbclean.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 64
size_t cleanbuf(ssize_t bufsize, char* buf);
int tagstatus;
int gettagstatus(void);
void settagstatus(int newtagstatus);
int main(int argc, char** argv)
{
/* set buffer */
ssize_t read_bytes;
char inputbuffer[BUFFER_SIZE+1];
char outputbuffer[BUFFER_SIZE+1];
/* check arguments */
if(argc != 2)
{
fprintf(stderr,"Usage: fbclean fbfile.fb2 \n");
return 0;
}
/* Open fb2 */
int f = open (argv[1],O_NOATIME|O_RDONLY);
if (f<0)
{
fprintf(stderr, "fbclean: Cannot open file '%s'\n",argv[1]);
return 1;
}
/* read buffer */
settagstatus(0);//No tags
while ((read_bytes = read (f, inputbuffer, BUFFER_SIZE)) > 0)
{
memset(outputbuffer,0,BUFFER_SIZE);
int len=cleanbuf(read_bytes,inputbuffer);
if (len>0)
{
inputbuffer[len]=0;/* Add null-terminator for C-string */
fputs(inputbuffer,stdout);
}
}
if (read_bytes < 0)
{
fprintf (stderr, "myread: Cannot read file\n");
return 1;
}
close(f);
return 0;
}
/* cleanbuf function */
size_t cleanbuf(ssize_t bufsize, char* buf)
{
/* return count of really copied bytes */
/* copy from buf to output=buf if need */
char *output=buf, *beg0=buf;buf--; //buf-- for start cycle
while ((++buf-beg0)<bufsize)
{
if (gettagstatus()==0) //outside a tag, main text
{
if (*buf!='<') //no start tag
{
*output++=*buf;
continue;
}
else
{
settagstatus(1);//new tag start
continue;
}
}
else //inside a tag
{
if (*buf=='>') //end tag
{
settagstatus(0);//close tag
continue;
}
else
{
continue;
}
}
} //for
return output-beg0;
}
/* tagstatus functions */
int gettagstatus(void)
{
return tagstatus;
}
void settagstatus(int newtagstatus)
{
tagstatus=newtagstatus;
return;
}
Делаем тестовый пример, где-то на 10Гб, просто копируя исходный файл
create-test.sh
#!/bin/bash
for ((i=1; i<=10000; i++))
do
cat $1 >> $2
done
Тестируем.
$ time ./fbclean 1.fb2 > /dev/null
real 0m47.431s
user 0m16.348s
sys 0m31.060s
$ time w3m -dump -cols 130 -s -T text/html 1.fb2 > /dev/null
Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS
Aborted
real 1m43.151s
user 5m58.757s
sys 0m4.496s
Я правда не уверен, что такие большие файлы встретятся, это просто тест, но все же.
Исходная версия praseodim, :
Спасибо, интересная возможность, даже не знал, что w3m можно использовать.
Но все же w3m и существенно медленнее даже без mmap получается. А главное, не может слишком большой файл обработать. Например, если 11G подсунуть валится с ошибкой «Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS» Aborted
fbclean.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 64
size_t cleanbuf(ssize_t bufsize, char* buf);
int tagstatus;
int gettagstatus(void);
void settagstatus(int newtagstatus);
int main(int argc, char** argv)
{
/* set buffer */
ssize_t read_bytes;
char inputbuffer[BUFFER_SIZE+1];
char outputbuffer[BUFFER_SIZE+1];
/* check arguments */
if(argc != 2)
{
fprintf(stderr,"Usage: fbclean fbfile.fb2 \n");
return 0;
}
/* Open fb2 */
int f = open (argv[1],O_NOATIME|O_RDONLY);
if (f<0)
{
fprintf(stderr, "fbclean: Cannot open file '%s'\n",argv[1]);
return 1;
}
/* read buffer */
settagstatus(0);//No tags
while ((read_bytes = read (f, inputbuffer, BUFFER_SIZE)) > 0)
{
memset(outputbuffer,0,BUFFER_SIZE);
int len=cleanbuf(read_bytes,inputbuffer);
if (len>0)
{
inputbuffer[len]=0;/* Add null-terminator for C-string */
fputs(inputbuffer,stdout);
}
}
if (read_bytes < 0)
{
fprintf (stderr, "myread: Cannot read file\n");
return 1;
}
close(f);
return 0;
}
/* cleanbuf function */
size_t cleanbuf(ssize_t bufsize, char* buf)
{
/* return count of really copied bytes */
/* copy from buf to output=buf if need */
char *output=buf, *beg0=buf;buf--; //buf-- for start cycle
while ((++buf-beg0)<bufsize)
{
if (gettagstatus()==0) //outside a tag, main text
{
if (*buf!='<') //no start tag
{
*output++=*buf;
continue;
}
else
{
settagstatus(1);//new tag start
continue;
}
}
else //inside a tag
{
if (*buf=='>') //end tag
{
settagstatus(0);//close tag
continue;
}
else
{
continue;
}
}
} //for
return output-beg0;
}
/* tagstatus functions */
int gettagstatus(void)
{
return tagstatus;
}
void settagstatus(int newtagstatus)
{
tagstatus=newtagstatus;
return;
}
Делаем тестовый пример, где-то на 10Гб, просто копируя исходный файл
create-test.sh
#!/bin/bash
for ((i=1; i<=10000; i++))
do
cat $1 >> $2
done
Тестируем.
$ time ./fbclean 1.fb2 > /dev/null
real 0m47.431s
user 0m16.348s
sys 0m31.060s
$ time w3m -dump -cols 130 -s -T text/html 1.fb2 > /dev/null
Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS
Aborted
real 1m43.151s
user 5m58.757s
sys 0m4.496s