do not loose read in quotes
diff --git a/ini_private.go b/ini_private.go
index 93658d6..3a44bd6 100644
--- a/ini_private.go
+++ b/ini_private.go
@@ -14,6 +14,7 @@
 type iniValue struct {
 	Name       string
 	Value      string
+	Quoted     bool
 	LineNumber uint
 }
 
@@ -115,19 +116,19 @@
 			kind = val.Type().Elem().Kind()
 
 			if val.Len() == 0 {
-				writeOption(writer, oname, kind, "", "", true)
+				writeOption(writer, oname, kind, "", "", true, option.iniQuote)
 			} else {
 				for idx := 0; idx < val.Len(); idx++ {
 					v, _ := convertToString(val.Index(idx), option.tag)
 
-					writeOption(writer, oname, kind, "", v, commentOption)
+					writeOption(writer, oname, kind, "", v, commentOption, option.iniQuote)
 				}
 			}
 		case reflect.Map:
 			kind = val.Type().Elem().Kind()
 
 			if val.Len() == 0 {
-				writeOption(writer, oname, kind, "", "", true)
+				writeOption(writer, oname, kind, "", "", true, option.iniQuote)
 			} else {
 				mkeys := val.MapKeys()
 				keys := make([]string, len(val.MapKeys()))
@@ -143,13 +144,13 @@
 				for _, k := range keys {
 					v, _ := convertToString(val.MapIndex(kkmap[k]), option.tag)
 
-					writeOption(writer, oname, kind, k, v, commentOption)
+					writeOption(writer, oname, kind, k, v, commentOption, option.iniQuote)
 				}
 			}
 		default:
 			v, _ := convertToString(val, option.tag)
 
-			writeOption(writer, oname, kind, "", v, commentOption)
+			writeOption(writer, oname, kind, "", v, commentOption, option.iniQuote)
 		}
 
 		if comments {
@@ -162,9 +163,9 @@
 	}
 }
 
-func writeOption(writer io.Writer, optionName string, optionType reflect.Kind, optionKey string, optionValue string, commentOption bool) {
-	if optionType == reflect.String {
-		optionValue = quoteIfNeeded(optionValue)
+func writeOption(writer io.Writer, optionName string, optionType reflect.Kind, optionKey string, optionValue string, commentOption bool, forceQuote bool) {
+	if forceQuote || (optionType == reflect.String && !strconv.CanBackquote(optionValue)) {
+		optionValue = strconv.Quote(optionValue)
 	}
 
 	comment := ""
@@ -307,10 +308,13 @@
 
 		name := strings.TrimSpace(keyval[0])
 		value := strings.TrimSpace(keyval[1])
+		quoted := false
 
 		if len(value) != 0 && value[0] == '"' {
 			if v, err := strconv.Unquote(value); err == nil {
 				value = v
+
+				quoted = true
 			} else {
 				return nil, &IniError{
 					Message:    err.Error(),
@@ -323,6 +327,7 @@
 		section = append(section, iniValue{
 			Name:       name,
 			Value:      value,
+			Quoted:     quoted,
 			LineNumber: lineno,
 		})
 
@@ -406,6 +411,8 @@
 					if len(parts) == 2 && parts[1][0] == '"' {
 						if v, err := strconv.Unquote(parts[1]); err == nil {
 							parts[1] = v
+
+							inival.Quoted = true
 						} else {
 							return &IniError{
 								Message:    err.Error(),
@@ -429,6 +436,9 @@
 				}
 			}
 
+			// always quote in case one value of the option uses quotes
+			opt.iniQuote = opt.iniQuote || inival.Quoted
+
 			opt.tag.Set("_read-ini-name", inival.Name)
 		}
 	}
diff --git a/ini_test.go b/ini_test.go
index 888e56c..47afd37 100644
--- a/ini_test.go
+++ b/ini_test.go
@@ -299,6 +299,103 @@
 	}
 }
 
+func TestReadAndWriteIni(t *testing.T) {
+	var tests = []struct {
+		options IniOptions
+		read    string
+		write   string
+	}{
+		{
+			IniIncludeComments,
+			`[Application Options]
+; Show verbose debug information
+verbose = true
+verbose = true
+
+; Test default value
+Default = "quote me"
+
+; Test default array value
+DefaultArray = 1
+DefaultArray = "2"
+DefaultArray = 3
+
+; Testdefault map value
+; DefaultMap =
+
+; Test env-default1 value
+EnvDefault1 = env-def
+
+; Test env-default2 value
+EnvDefault2 = env-def
+
+[Other Options]
+; A slice of strings
+; StringSlice =
+
+; A map from string to int
+int-map = a:2
+int-map = b:"3"
+
+`,
+			`[Application Options]
+; Show verbose debug information
+verbose = true
+verbose = true
+
+; Test default value
+Default = "quote me"
+
+; Test default array value
+DefaultArray = "1"
+DefaultArray = "2"
+DefaultArray = "3"
+
+; Testdefault map value
+; DefaultMap =
+
+; Test env-default1 value
+EnvDefault1 = env-def
+
+; Test env-default2 value
+EnvDefault2 = env-def
+
+[Other Options]
+; A slice of strings
+; StringSlice =
+
+; A map from string to int
+int-map = a:"2"
+int-map = b:"3"
+
+`,
+		},
+	}
+
+	for _, test := range tests {
+		var opts helpOptions
+
+		p := NewNamedParser("TestIni", Default)
+		p.AddGroup("Application Options", "The application options", &opts)
+
+		inip := NewIniParser(p)
+
+		read := strings.NewReader(test.read)
+		err := inip.Parse(read)
+		if err != nil {
+			t.Fatalf("Unexpected error: %s", err)
+		}
+
+		var write bytes.Buffer
+		inip.Write(&write, test.options)
+
+		got := write.String()
+
+		msg := fmt.Sprintf("with ini options %b", test.options)
+		assertDiff(t, got, test.write, msg)
+	}
+}
+
 func TestReadIniWrongQuoting(t *testing.T) {
 	var tests = []struct {
 		iniFile    string
diff --git a/option.go b/option.go
index 86bd030..29e702c 100644
--- a/option.go
+++ b/option.go
@@ -68,6 +68,9 @@
 	// The struct field value which the option represents.
 	value reflect.Value
 
+	// Determines if the option will be always quoted in the INI output
+	iniQuote bool
+
 	tag   multiTag
 	isSet bool
 }