windows - Læsning af de sidste n linjer fra en enorm tekstfil

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har prøvet noget som dette


file\_in <- file("myfile.log","r")
x <- readLines(file\_in, n=-100)


men jeg venter stadig ...


Enhver hjælp ville blive meget værdsat

Bedste reference


Jeg bruger scan til dette, hvis du ved, hvor mange linjer loggen har:


scan("foo.txt",sep="
",what="char(0)",skip=100)


Hvis du ikke har nogen anelse om, hvor mange du skal springe over, har du ikke andet valg end at flytte til enten



  • læsning i alt og tager de sidste n linjer (hvis det er muligt)

  • ved hjælp af scan("foo.txt",sep=" ",what=list(NULL)) for at finde ud af, hvor mange poster der er, eller

  • bruger en algoritme til at gå igennem filen og kun holde de sidste n linjer hver gang



Den sidste mulighed kan se ud:


ReadLastLines <- function(x,n,...){    
  con <- file(x)
  open(con)
  out <- scan(con,n,what="char(0)",sep="
",quiet=TRUE,...)

  while(TRUE){
    tmp <- scan(con,1,what="char(0)",sep="
",quiet=TRUE)
    if(length(tmp)==0) {close(con) ; break }
    out <- c(out[-1],tmp)
  }
  out
}


tillader:


ReadLastLines("foo.txt",100)


eller


ReadLastLines("foo.txt",100,skip=1e+7)


hvis du ved, du har mere end 10 millioner linjer. Dette kan spare på læsetiden, når du begynder at have ekstremt store logfiler.





EDIT: Faktisk bruger jeg ikke engang R for dette i betragtning af størrelsen på din fil. På Unix kan du bruge kommandoen hale. Der er også en Windows-version til det, et eller andet sted i et værktøjssæt. Jeg gjorde ikke ' T Prøv det dog endnu. [17]

Andre referencer 1


Du kan gøre dette med read.table ved at angive parameteren skip. Hvis dine linjer ikke skal analyseres til variabler, skal du angive separatoren som ' ' som @Joris Meys påpeget nedenfor, og indstil også as.is=TRUE for at få tegnvektorer i stedet for faktorer.


Lille eksempel (spring over de første 2000 linjer):


df <- read.table('foo.txt', sep='
', as.is=TRUE, skip=2000)

Andre referencer 2


Som @JorisMeys allerede nævnt vil unix-kommandoen tail være den nemmeste måde at løse dette problem på. Jeg vil dog foreslå en seek baseret R løsning, der begynder at læse filen fra slutningen af ​​filen:


tailfile <- function(file, n) {
  bufferSize <- 1024L
  size <- file.info(file)$size

  if (size < bufferSize) {
    bufferSize <- size
  }

  pos <- size - bufferSize
  text <- character()
  k <- 0L

  f <- file(file, "rb")
  on.exit(close(f))

  while(TRUE) {
    seek(f, where=pos)
    chars <- readChar(f, nchars=bufferSize)
    k <- k + length(gregexpr(pattern="\n", text=chars)[**1L**])
    text <- paste0(text, chars)

    if (k > n || pos == 0L) {
      break
    }

    pos <- max(pos-bufferSize, 0L)
  }

  tail(strsplit(text, "\n")[**1L**], n)
}

tailfile(file, n=100)