I have an ESRI ASCII file with usual 6 rows of headers followed by elevation values in metres. The NO_DATA value in the header is set to -9999.

I am trying to convert this ASCII to XYZ using gdal_translate and do not want to include nodata values of -9999 in the output XYZ File. I am using the a_nodata command to ignore -a_nodata values in the output XYZ file however have so far been unsuccessful in getting this to work. I'm hoping someone can help me out as to where I am going wrong with the -a_nodata command. I've included my current code below which creates the XYZ file but does not ignore no data values.

gdal_translate -of XYZ D:\WORK\COASTAL_PRODUCTS\P_10853\ASCII_GRIDS\DSM\tq6575_20161005lidaru.asc D:\WORK\COASTAL_PRODUCTS\P_10853\ASCII_XYZ\DSM\tq6575_20161005lidaru.txt -a_nodata -9999 
  • Comments are correct on my answer - this will only assign no data values to these (as opposed to removing them entirely). @Luke's answer will work, or else you can use gdal_calc and avoid setting nodata values entirely: gis.stackexchange.com/questions/121110/…
    – AlecZ
    Nov 13, 2017 at 18:57

3 Answers 3


The nodata values are part of a raster. The XYZ format is still a raster format and needs the nodata values to maintain a regular grid. This is why you can't get gdal not to write them out. If it did, it wouldn't be able to read it again.

However you can avoid writing NoData values to your output by stripping them out with an external program. To do this, write the output to stdout then pipe to findstr to filter it before writing to your csv:

gdal_translate -q -of xyz -co ADD_HEADER_LINE=YES -co COLUMN_SEPARATOR="," input_raster /vsistdout | findstr /V /C:"your_nodata_value" > output.csv 
  • For anyone reading this answer, it absolutely worked great for me. I had looked for a long while to figure this out.
    – David
    Jul 17, 2021 at 19:43
  • @David see also gis.stackexchange.com/a/201232/2856
    – user2856
    Jul 17, 2021 at 22:19
  • Is it possible to exclude a range of data? Instead of /C:"999" it would be, say... /C:"500-999" (exclude everything 500 to 999).
    – David
    Jul 19, 2021 at 0:18
  • @David Nope, but use the ogr2ogr syntax in my comments (below and on your grib2 question) and use something like gdal_translate -q -of XYZ -co ADD_HEADER_LINE=YES input.grib2 /vsistdout/ | ogr2ogr -f CSV -sql "SELECT X,Y,Z FROM layer WHERE cast(Z as float) < 500 or cast(Z as float) > 999" output.csv CSV:/vsistdin/ -lco SEPARATOR=SPACE
    – user2856
    Jul 19, 2021 at 1:19

This task can be accomplished in two steps: first, convert the ESRI ASCII file into an XYZ one, adding the header line and using the csv extension in the output file. Finally, use a bit of OGR SQL to skip records with NoData values:

gdal_translate -of XYZ input_ASCII_with_NoData.asc output_XYZ_with_NoData.csv -co ADD_HEADER_LINE=YES
ogr2ogr -f CSV -sql "SELECT x, y, z FROM output_XYZ_with_NoData WHERE z != '-9999'" output_XYZ_without_NoData.csv output_XYZ_with_NoData.csv -lco SEPARATOR=SPACE
  • Great answer, more OS agnostic than mine. Here's a one-liner using this syntax ` gdal_translate -q -of XYZ -co ADD_HEADER_LINE=YES input_raster /vsistdout/ | ogr2ogr -f CSV -sql "SELECT X,Y,Z FROM layer WHERE Z != '-9999'" output.csv CSV:/vsistdin/ -lco SEPARATOR=SPACE`
    – user2856
    Jul 18, 2021 at 6:51

You're almost there - also need quotes on the output format but this should work fine.

gdal_translate -of "XYZ" D:\WORK\COASTAL_PRODUCTS\P_10853\ASCII_XYZ\DSM\tq6575_20161005lidaru.asc D:\WORK\COASTAL_PRODUCTS\P_10853\ASCII_GRIDS\DSM\tq6575_20161005lidaru.xyz -a_nodata "value [-9999]" 
  • This won't work . Nodata will still get written. .
    – user2856
    Nov 13, 2017 at 18:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.