read.fwf <-
function(file, widths, header = FALSE, sep = "\t", as.is = FALSE,
         skip = 0, row.names, col.names, n = -1, buffersize=2000, ...)
{
    doone <- function(x) {
        x <- substring(x, first, last)
        x[nchar(x)==0] <- as.character(NA)
        x
    }

    if (is.list(widths)) {
      recordlength<-length(widths)
      widths<-do.call("c",widths)
    } else recordlength<-1

    drop<- (widths<0)
    widths<-abs(widths)


    buffersize<-(buffersize %/% recordlength)* recordlength

    FILENAME <- tempfile("Rfwf.")
    on.exit(unlink(FILENAME))
    FILE<-file(FILENAME,"a")
    on.exit(close(FILE),add=TRUE)

    if (is.character(file)) {
      file <- file(file,"r")
      on.exit(close(file),add=TRUE)
    } else if (!isOpen(file)) {
      file <- open(file,"r")
      on.exit(close(file),add=TRUE)
    }

    if (skip)
      readLines(file,n=skip)
    if (header){
      headerline<-readLines(file,n=1)
      cat(FILE,headerline,"\n")
    }

    repeat({
      if (n==-1)
        thisblock<-buffersize
      else
        thisblock<-min(buffersize,n)

      raw <- readLines(file, n=thisblock)
      nread<-length(raw)
      if (recordlength>1 &&  nread %% recordlength){
        raw<-raw[1:(nread-nread %% recordlength)]
        warning("Last record incomplete, ",nread %% recordlength," lines discarded")
      }
      if (recordlength>1){
        raw<-matrix(raw,nrow=recordlength)
        raw<-apply(raw,2,paste,collapse="")
      }

      st <- c(1, 1+cumsum(widths))
      first <- st[-length(st)][!drop]
      last <- cumsum(widths)[!drop]
      cat(file = FILE, sapply(raw, doone),
          sep = c(rep(sep, length.out = length(first)-1), "\n"))

      if (length(raw)<thisblock)
        break
      if (n>0)
        n<- n - length(raw)
    })

    close(FILE)
    FILE<-file(FILENAME,"r")
    read.table(file = FILE, header = header, sep = sep, as.is = as.is,
	       skip = skip, row.names = row.names, col.names =
               col.names, quote="", ...)
}
