Чтение последних n строк из огромного текстового файла - PullRequest
6 голосов
/ 08 апреля 2011

Я пробовал что-то вроде этого

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

, но я все еще жду ...

Любая помощь будет принята с благодарностью

Ответы [ 3 ]

9 голосов
/ 08 апреля 2011

Я бы использовал scan для этого, если вы знаете, сколько строк в журнале:

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

Если вы не знаете, сколько вам нужно пропустить, у вас нет выбора, кромечтобы перейти к

  • чтению во всем и взятию последних n строк (если это возможно),
  • с использованием scan("foo.txt",sep="\n",what=list(NULL)) для определения количества записей или
  • используя некоторый алгоритм для просмотра файла, каждый раз сохраняя только последние n строк

Последний параметр может выглядеть следующим образом:

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

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

, позволяющий:

ReadLastLines("foo.txt",100)

или

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

, если вы знаете, что у вас более 10 миллионов строк.Это может сэкономить время чтения, когда вы начинаете иметь очень большие журналы.


РЕДАКТИРОВАТЬ: На самом деле, я бы даже не использовал R для этого, учитывая размер вашего файла.В Unix вы можете использовать команду tail .Для этого есть версия для Windows, где-то в наборе инструментов.Я еще не пробовал это.

4 голосов
/ 08 апреля 2011

Вы можете сделать это с помощью read.table, указав параметр skip. Если ваши строки не нужно разбирать на переменные, укажите разделитель равным '\n', как @Joris Meys указал ниже, а также установите as.is=TRUE для получения векторов символов вместо факторов.

Небольшой пример (пропуская первые 2000 строк):

df <- read.table('foo.txt', sep='\n', as.is=TRUE, skip=2000)
0 голосов
/ 21 июня 2015

Как уже упоминал @JorisMeys, команда unix tail будет самым простым способом решения этой проблемы.Однако я хочу предложить решение R на основе seek, которое начинает чтение файла с конца файла:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...