LINUX.ORG.RU

История изменений

Исправление 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