public void Write(
            TzdbDatabase database,
            WindowsZones cldrWindowsZones,
            IDictionary<string, string> additionalWindowsNameToIdMappings,
            Stream stream)
        {
            FieldCollection fields = new FieldCollection();

            var zones = database.GenerateDateTimeZones().ToList();
            var stringPool = CreateOptimizedStringPool(zones, database.ZoneLocations, database.Zone1970Locations, cldrWindowsZones);
            
            // First assemble the fields (writing to the string pool as we go)
            foreach (var zone in zones)
            {
                var zoneField = fields.AddField(TzdbStreamFieldId.TimeZone, stringPool);
                WriteZone(zone, zoneField.Writer);
            }

            fields.AddField(TzdbStreamFieldId.TzdbVersion, null).Writer.WriteString(database.Version);

            // Normalize the aliases
            var timeZoneMap = new Dictionary<string, string>();
            foreach (var key in database.Aliases.Keys)
            {
                var value = database.Aliases[key];
                while (database.Aliases.ContainsKey(value))
                {
                    value = database.Aliases[value];
                }
                timeZoneMap.Add(key, value);
            }

            fields.AddField(TzdbStreamFieldId.TzdbIdMap, stringPool).Writer.WriteDictionary(timeZoneMap);

            // Windows mappings
            cldrWindowsZones.Write(fields.AddField(TzdbStreamFieldId.CldrSupplementalWindowsZones, stringPool).Writer);
            fields.AddField(TzdbStreamFieldId.WindowsAdditionalStandardNameToIdMapping, stringPool).Writer.WriteDictionary
                (additionalWindowsNameToIdMappings.ToDictionary(pair => pair.Key, pair => cldrWindowsZones.PrimaryMapping[pair.Value]));

            // Zone locations, if any.
            var zoneLocations = database.ZoneLocations;
            if (zoneLocations != null)
            {
                var field = fields.AddField(TzdbStreamFieldId.ZoneLocations, stringPool);
                field.Writer.WriteCount(zoneLocations.Count);
                foreach (var zoneLocation in zoneLocations)
                {
                    zoneLocation.Write(field.Writer);
                }
            }

            // Zone 1970 locations, if any.
            var zone1970Locations = database.Zone1970Locations;
            if (zone1970Locations != null)
            {
                var field = fields.AddField(TzdbStreamFieldId.Zone1970Locations, stringPool);
                field.Writer.WriteCount(zone1970Locations.Count);
                foreach (var zoneLocation in zone1970Locations)
                {
                    zoneLocation.Write(field.Writer);
                }
            }

            var stringPoolField = fields.AddField(TzdbStreamFieldId.StringPool, null);
            stringPoolField.Writer.WriteCount(stringPool.Count);
            foreach (string value in stringPool)
            {
                stringPoolField.Writer.WriteString(value);
            }

            // Now write all the fields out, in the right order.
            new BinaryWriter(stream).Write(Version);
            fields.WriteTo(stream);
        }
 /// <summary>
 /// Creates a string pool which contains the most commonly-used strings within the given set
 /// of zones first. This will allow them to be more efficiently represented when we write them out for real.
 /// </summary>
 private static List<string> CreateOptimizedStringPool(
     IEnumerable<DateTimeZone> zones,
     IEnumerable<TzdbZoneLocation> zoneLocations,
     IEnumerable<TzdbZone1970Location> zone1970Locations,
     WindowsZones cldrWindowsZones)
 {
     var optimizingWriter = new StringPoolOptimizingFakeWriter();
     foreach (var zone in zones)
     {
         optimizingWriter.WriteString(zone.Id);
         WriteZone(zone, optimizingWriter);
     }
     if (zoneLocations != null)
     {
         foreach (var location in zoneLocations)
         {
             location.Write(optimizingWriter);
         }
     }
     if (zone1970Locations != null)
     {
         foreach (var location in zone1970Locations)
         {
             location.Write(optimizingWriter);
         }
     }
     cldrWindowsZones.Write(optimizingWriter);
     return optimizingWriter.CreatePool();
 }