Ниже приведена обновленная версия с базовым вводом / выводом в стиле C, которая работает в десять раз быстрее, чем в режиме ostream. Однако есть еще две проблемы:
1: когда я использую fscanf, чтобы получить размерность nrows, ncols из заголовков, целочисленное значение nrows, ncols менялось несколько раз, я не знаю, мне нужно ввести два новых keepnrows, keepncols, чтобы сразу после fscanf сохранить значение, я думаю это должно быть исправлено, но я не знаю, как это исправить.
PS: обновлено 6 апреля. Я нашел, что приводит к ошибке, потому что значение tmpvalue не инициализировано, см. код ниже. Но мне интересно ПОЧЕМУ?
// float tmpvalue;
float tmpvalue = -9998.0;
NCOLS: 400
NROWS: 600
XLLCORNER: -10.000000
YLLCORNER: -20.000000
CELLSIZE: 0,050000
NODATA_value: -9999.000000
nrows: 1635147585, NLS; 141; 141; 141; 141; 1 1023 *
NROWS: 1635147585
NCOLS: 1413563471
keepnrows: 600
keepncols: 400
2: о том, как исправить 'fscanf (fp, "% 10.6f", & tmpvalue) ', с предупреждением: неизвестный символ типа преобразования'. ' в формате [-Wformat]. в настоящее время я получаю значение с плавающей точкой, как 0,001000000584, в то время как оно должно быть 0,001.
#include <Rcpp.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <math.h>
#include <algorithm>
using namespace std;
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix cppread_asc(std::string path, const bool maskNA=true, const bool fast=true, const bool debug=false) {
int ncols, keepncols;
int nrows, keepnrows;
float cellsize;
float xllcorner;
float yllcorner;
float nodata_value;
//float tmpvalue; //This will result in serious erros that the ncols,nrows change always, I do not know why?
float tmpvalue=-9998.0;
std::string tmpstr;
char tmpstring;
if(fast){
FILE *fp = fopen(path.c_str(), "r");
if (fp == NULL) {
perror("error opening file");
}
fscanf(fp,"%s",&tmpstring);
if(debug) printf("%s: ",&tmpstring);
fscanf(fp,"%i",&ncols);
keepncols=ncols;
if(debug) printf("%i\n",ncols);
fscanf(fp,"%s",&tmpstring);
if(debug) printf("%s: ",&tmpstring);
fscanf(fp,"%i",&nrows);
keepnrows=nrows;
if(debug) printf("%i\n",nrows);
fscanf(fp,"%s",&tmpstring);
if(debug) printf("%s: ",&tmpstring);
fscanf(fp,"%f",&xllcorner);
if(debug) printf("%f\n",xllcorner);
fscanf(fp,"%s",&tmpstring);
if(debug) printf("%s: ",&tmpstring);
fscanf(fp,"%f",&yllcorner);
if(debug) printf("%f\n",yllcorner);
fscanf(fp,"%s",&tmpstring);
if(debug) printf("%s: ",&tmpstring);
fscanf(fp,"%f",&cellsize);
if(debug) printf("%f\n",cellsize);
fscanf(fp,"%s",&tmpstring);
if(debug) printf("%s: ",&tmpstring);
fscanf(fp,"%f",&nodata_value);
if(debug) printf("%f\n",nodata_value);
if(debug){
Rcout<< "nrows:" << nrows << ", ncols;" << ncols << ";\n";
}
printf("NROWS: %i\n",nrows); printf("NCOLS: %i\n",ncols);
printf("keepnrows: %i\n",keepnrows); printf("keepncols: %i\n",keepncols);
nrows=keepnrows;
ncols=keepncols;
NumericMatrix output(nrows,ncols);
for(int row=0; row<nrows; ++row){
for(int col=0; col<ncols; ++col){
// fscanf(fp,"%0.20f", &tmpvalue);
fscanf(fp,"%10f", &tmpvalue);
output(row,col)=tmpvalue;
if(debug && col<3 && row<3){
Rcout<< "row: " << row <<", column: " << col <<" value: " << output(row,col) <<"tmpvalue: " <<tmpvalue<< ";\n";
}
if(maskNA){
if(debug && row<2 && col<2){
Rcout<< "start to mask NA\n";
}
if(output(row,col)<=nodata_value){
output(row,col)=NA_REAL;
}
}
}
}
fclose(fp);
return(output);
}else{
std::ifstream ascfile(path.c_str());
if(ascfile.fail()){
perror("Error, file does not exist");
}else{
// read the georeferencing data and metadata
ascfile
>> tmpstr >> ncols
>> tmpstr >> nrows
>> tmpstr >> xllcorner
>> tmpstr >> yllcorner
>> tmpstr >> cellsize
>> tmpstr >> nodata_value;
// if(debug){
// Rcout<< "nrows:" << nrows << ", ncols;" << ncols << ";\n";
// }
NumericMatrix output(nrows,ncols);
for(int row=0; row<nrows; ++row){
for(int col=0; col<ncols; ++col){
ascfile >> output(row,col);
if(maskNA){
if(output(row,col)<=nodata_value){
output(row,col)=NA_REAL;
}
}
}
}
ascfile.close();
return(output);
}
}
}
/*** R
require(raster)
require(microbenchmark)
r=raster(nrows=600, ncols=400, xmn=-10, xmx=10, ymn=-20, ymx=10, vals=0.001*1:(600*400))
writeRaster(r,filename= "test.asc", format = "ascii", overwrite=TRUE)
microbenchmark(
new1<<-cppread_asc("test.asc",maskNA=TRUE,fast=TRUE,debug=TRUE),
new2<<-cppread_asc("test.asc",maskNA=TRUE,fast=FALSE,debug=TRUE),
new3<<-matrix(getValues(raster("test.asc")),nrow=600,ncol=400,byrow=TRUE),
print(identical(new1,new2)),print(identical(new2,new3)),times=1
)
*/
#benchmark results:
# min lq mean median uq
#Rcpp_read : 329938.034 329938.034 329938.034 329938.034 329938.034
#Rcpp_read : 9097437.947 9097437.947 9097437.947 9097437.947 9097437.947
#raster_read: 409822.642 409822.642 409822.642 409822.642 409822.642