code: public CsvReader getCsvReader(ZipFile zipFile, SQLErrorStorage sqlErrorStorage) {
          final String tableFileName = this.name + ".txt";
          ZipEntry entry = zipFile.getEntry(tableFileName);
          if (entry == null) {
              // Table was not found, check if it is in a subdirectory.
              Enumeration<? extends ZipEntry> entries = zipFile.entries();
              while (entries.hasMoreElements()) {
                  ZipEntry e = entries.nextElement();
                  if (e.getName().endsWith(tableFileName)) {
                      entry = e;
                      if (sqlErrorStorage != null) sqlErrorStorage.storeError(NewGTFSError.forTable(this, TABLE_IN_SUBDIRECTORY));
                      break;
                  }
              }
          }
          if (entry == null) return null;
          try {
              InputStream zipInputStream = zipFile.getInputStream(entry);
              // Skip any byte order mark that may be present. Files must be UTF-8,
              // but the GTFS spec says that "files that include the UTF byte order mark are acceptable".
              InputStream bomInputStream = new BOMInputStream(zipInputStream);
              CsvReader csvReader = new CsvReader(bomInputStream, ',', Charset.forName("UTF8"));
              csvReader.readHeaders();
              return csvReader;
          } catch (IOException e) {
              LOG.error("Exception while opening zip entry: {}", e);
              e.printStackTrace();
              return null;
          }
      }
docs: In GTFS feeds, all files are supposed to be in the root of the zip file, but feed producers often put them
  in a subdirectory. This function will search subdirectories if the entry is not found in the root.
  It records an error if the entry is in a subdirectory (as long as errorStorage is not null).
  It then creates a CSV reader for that table if it's found.