@@ -84,7 +84,14 @@ static public boolean isValidFile(RandomAccessFile raf) {
84
84
int len = GribNumbers .uint3 (raf );
85
85
int edition = raf .read (); // read at byte 8
86
86
if (edition != 1 ) return false ;
87
-
87
+
88
+ /* Due to a trick done by ECMWF's GRIBEX to support large GRIBs, we need a special treatment
89
+ * to fix the length of the GRIB message. See:
90
+ * https://software.ecmwf.int/wiki/display/EMOS/Changes+in+cycle+000281
91
+ * https://github.com/Unidata/thredds/issues/445
92
+ */
93
+ len = getFixedTotalLengthEcmwfLargeGrib (raf ,len );
94
+
88
95
// check ending = 7777
89
96
if (len > raf .length ()) return false ;
90
97
if (allowBadIsLength ) return true ;
@@ -100,7 +107,40 @@ static public boolean isValidFile(RandomAccessFile raf) {
100
107
}
101
108
}
102
109
103
- ////////////////////////////////////////////////////////////
110
+ static int getFixedTotalLengthEcmwfLargeGrib (RandomAccessFile raf , int len ) throws IOException {
111
+ int lenActual =len ;
112
+ //int lenS4Actual=0;
113
+ //int sizeSection4=0;
114
+ if ((len & 0x800000 ) == 0x800000 ) {
115
+ long pos0 = raf .getFilePointer (); // remember the actual pos
116
+ int lenS1 = GribNumbers .uint3 (raf ); // section1Length
117
+ raf .skipBytes (1 ); // table2Version
118
+ if (GribNumbers .uint (raf ) == 98 ) { // center (if ECMWF make the black magic)
119
+ raf .skipBytes (2 ); // generatingProcessIdentifier, gridDefinition
120
+ int s1f = GribNumbers .uint (raf ); // section1Flags
121
+ raf .skipBytes (lenS1 - (3 + 5 )); // skips to next section
122
+ int lenS2 = 0 ;
123
+ int lenS3 = 0 ;
124
+ if ((s1f & 128 ) == 128 ) { // section2 GDS exists
125
+ lenS2 = GribNumbers .uint3 (raf ); // section2Length
126
+ raf .skipBytes (lenS2 - 3 ); // skips to next section
127
+ }
128
+ if ((s1f & 64 ) == 64 ) { // section3 BMS exists
129
+ lenS3 = GribNumbers .uint3 (raf ); // section3Length
130
+ raf .skipBytes (lenS3 - 3 ); // skips to next section
131
+ }
132
+ int lenS4 = GribNumbers .uint3 (raf ); // section4Length
133
+ if (lenS4 < 120 ) { // here we are!!!!
134
+ lenActual = (len & 0x7FFFFF ) * 120 - lenS4 + 4 ; // the actual totalLength
135
+ //lenS4Actual = lenActual - 8 - lenS1 - lenS2 - lenS3 - 4; // the actual length for section4
136
+ }
137
+ }
138
+ raf .seek (pos0 ); // recall the pos
139
+ }
140
+ return lenActual ;
141
+ }
142
+
143
+ ////////////////////////////////////////////////////////////
104
144
105
145
private Map <Long , Grib1SectionGridDefinition > gdsMap = new HashMap <>();
106
146
private ucar .unidata .io .RandomAccessFile raf = null ;
@@ -199,10 +239,10 @@ public Grib1Record next() throws IOException {
199
239
if (debug ) System .out .printf (" read until %d grib ending at %d header ='%s' foundEnding=%s%n" ,
200
240
raf .getFilePointer (), ending , StringUtil2 .cleanup (header ), foundEnding );
201
241
202
- if (!foundEnding && allowBadIsLength )
242
+ if (!foundEnding && ( allowBadIsLength || is . isMessageLengthFixed ) )
203
243
foundEnding = checkEnding (dataSection .getStartingPosition () + dataSection .getLength ());
204
244
205
- if (!foundEnding && allowBadDsLength ) {
245
+ if (!foundEnding && ( allowBadDsLength || is . isMessageLengthFixed ) ) {
206
246
foundEnding = true ;
207
247
}
208
248
0 commit comments