diff --git a/src/swcio.cpp b/src/swcio.cpp
index 203f69eb1bdca8905145edb4edbe86d564682e9b..588d969d5d443d2edbacccc2d49a83b125e56c25 100644
--- a/src/swcio.cpp
+++ b/src/swcio.cpp
@@ -123,11 +123,46 @@ swc_record::kind parse_value_strict(std::istream &is, const swc_parser &parser)
 // swc_parser implementation
 //
 
+std::istream& swc_parser::safe_getline(std::istream& is, std::string& t)
+{
+    // Based on http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
+    t.clear();
+
+    // The characters in the stream are read one-by-one using a std::streambuf.
+    // That is faster than reading them one-by-one using the std::istream.
+    // Code that uses streambuf this way must be guarded by a sentry object.
+    // The sentry object performs various tasks,
+    // such as thread synchronization and updating the stream state.
+
+    std::istream::sentry se(is, true);
+    std::streambuf* sb = is.rdbuf();
+
+    for (;;) {
+        int c = sb->sbumpc();
+        switch (c) {
+        case '\n':
+            return is;
+        case '\r':
+            if (sb->sgetc() == '\n')
+                sb->sbumpc();
+            return is;
+        case EOF:
+            // Also handle the case when the last line has no line ending
+            if (t.empty())
+                is.setstate(std::ios::eofbit);
+            return is;
+        default:
+            t += (char)c;
+        }
+    }
+}
+
 std::istream &swc_parser::parse_record(std::istream &is, swc_record &record)
 {
     while (!is.eof() && !is.bad()) {
         // consume empty and comment lines first
-        std::getline(is, linebuff_);
+        safe_getline(is, linebuff_);
+
         ++lineno_;
         if (!linebuff_.empty() && !starts_with(linebuff_, comment_prefix_))
             break;
diff --git a/src/swcio.hpp b/src/swcio.hpp
index 70f979cda362f503a81965c274a5cdeb23ea5056..09c89f8112de9379ee3248a82935a410f3a94a3c 100644
--- a/src/swcio.hpp
+++ b/src/swcio.hpp
@@ -211,6 +211,9 @@ public:
 
     std::istream &parse_record(std::istream &is, swc_record &record);
 
+    // Getline version supporting both windows and linux line endings
+    std::istream &safe_getline(std::istream& is, std::string& t);
+
 private:
     // Read the record from a string stream; will be treated like a single line
     swc_record parse_record(std::istringstream &is);
diff --git a/tests/test_swcio.cpp b/tests/test_swcio.cpp
index 5ba0b991a865dfb397e5c1dbbb1e8813e71b628c..fed88fb33909ac6557e843c4dfce96394a5bd6cb 100644
--- a/tests/test_swcio.cpp
+++ b/tests/test_swcio.cpp
@@ -521,3 +521,37 @@ TEST(swc_parser, from_file_ball_and_stick)
 
     EXPECT_TRUE(nest::mc::cell_basic_equality(local_cell, cell));
 }
+
+// check that windows EOL are supported in linux.
+// This test is based on the ball_and_stick.swc with windows endings inserted
+// manually in a file stream, regression test for issue_34
+TEST(swc_parser, windows_eol)
+{
+    std::string datadir{ DATADIR };
+    auto fname = datadir + "/ball_and_stick.swc";
+    std::ifstream fid(fname);
+
+    // Check valid usage
+    std::stringstream is;
+    is << "# ball and stick model with\r\n";
+    is << "#   - soma with radius 12.6157/2\r\n";
+    is << "#   - dendrite with length 200 and radius 0.5\r\n";
+    is << "\r\n";
+    is << "1 1     0.0     0.0     0.0     6.30785 - 1\r\n";
+    is << "2 2     6.30785 0.0     0.0     0.5      1\r\n";
+    is << "3 2   206.30785 0.0     0.0     0.5      2\r\n";
+
+    // read the file into a cell object
+    auto cell = nest::mc::io::swc_read_cell(fid);
+
+    // verify that the correct number of nodes was read
+    EXPECT_EQ(cell.num_segments(), 2);
+    EXPECT_EQ(cell.num_compartments(), 2u);
+
+    // make an equivalent cell via C++ interface
+    nest::mc::cell local_cell;
+    local_cell.add_soma(6.30785);
+    local_cell.add_cable(0, nest::mc::segmentKind::dendrite, 0.5, 0.5, 200);
+
+    EXPECT_TRUE(nest::mc::cell_basic_equality(local_cell, cell));
+}