diff --git a/common/cpp/include/common/file_info.h b/common/cpp/include/common/file_info.h
index baa44781ee1f87bad3a2352357ca8f44b16ea678..a08967c1fccab31f17b4d11dd61f524870509e19 100644
--- a/common/cpp/include/common/file_info.h
+++ b/common/cpp/include/common/file_info.h
@@ -11,6 +11,7 @@ struct FileInfo {
     std::string base_name;
     std::string relative_path;
     std::chrono::system_clock::time_point modify_date;
+    uint64_t size;
 };
 
 typedef std::vector<uint8_t> FileData;
diff --git a/common/cpp/include/system_wrappers/io.h b/common/cpp/include/system_wrappers/io.h
index f8e8d686d19aa2a52900ea4f7d2a2dd1f80ae572..059b376c50001b308fca8b5110a2e876e8beef9c 100644
--- a/common/cpp/include/system_wrappers/io.h
+++ b/common/cpp/include/system_wrappers/io.h
@@ -1,6 +1,8 @@
 #ifndef HIDRA2_SYSTEM_WRAPPERS__IO_H
 #define HIDRA2_SYSTEM_WRAPPERS__IO_H
 
+#include <cinttypes>
+
 #include <string>
 #include <vector>
 #include <chrono>
@@ -20,10 +22,11 @@ enum class IOErrors {
 
 IOErrors IOErrorFromErrno();
 
+
 class IO {
   public:
 
-    virtual FileData GetDataFromFile(const std::string& fname, IOErrors* err) = 0;
+    virtual FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) = 0;
 
     virtual int open(const char* __file, int __oflag) = 0;
     virtual int close(int __fd) = 0;
diff --git a/common/cpp/include/system_wrappers/system_io.h b/common/cpp/include/system_wrappers/system_io.h
index 9cb2214e5398fa866d98e12132b68c6aad6e5455..8bee9368436ea89f675626b083da4912b7348d4e 100644
--- a/common/cpp/include/system_wrappers/system_io.h
+++ b/common/cpp/include/system_wrappers/system_io.h
@@ -7,7 +7,7 @@ namespace hidra2 {
 
 class SystemIO final : public IO {
   public:
-    FileData GetDataFromFile(const std::string& fname, IOErrors* err);
+    FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) override;
     int open(const char* __file, int __oflag);
     int close(int __fd);
     ssize_t read(int __fd, void* buf, size_t count);
diff --git a/common/cpp/src/system_io.cpp b/common/cpp/src/system_io.cpp
index b706699810ef0197b854dfda458e69d22e2e9493..6f012a9f975d1c4d2995bbdaed4d3aa4f9c6c7e7 100644
--- a/common/cpp/src/system_io.cpp
+++ b/common/cpp/src/system_io.cpp
@@ -1,34 +1,62 @@
 #include <fcntl.h>
 #include <unistd.h>
+
 #include <system_wrappers/system_io.h>
 
-hidra2::FileData hidra2::SystemIO::GetDataFromFile(const std::string& fname, IOErrors* err) {
-    int fd = open(fname.c_str(), O_RDONLY);
+namespace hidra2 {
+
+void ReadWholeFile(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) {
+    ssize_t totalbytes = 0;
+    ssize_t readbytes = 0;
+    do {
+        readbytes = read(fd, array + totalbytes, fsize);
+        totalbytes += readbytes;
+    } while (readbytes > 0 && totalbytes < fsize);
 
+    if (totalbytes != fsize) {
+        *err = IOErrors::READ_ERROR;
+    }
+}
+
+FileData SystemIO::GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) {
+    int fd = open(fname.c_str(), O_RDONLY);
     *err = IOErrorFromErrno();
+    if (*err != IOErrors::NO_ERROR) {
+        return {};
+    }
+
+    FileData data(fsize);
 
+    ReadWholeFile(fd, &data[0], fsize, err);
     if (*err != IOErrors::NO_ERROR) {
+        close(fd);
         return {};
     }
-    *err = IOErrors::READ_ERROR;
+
     close(fd);
-    return {};
+    *err = IOErrorFromErrno();
+    if (*err != IOErrors::NO_ERROR) {
+        return {};
+    }
 
+    return data;
 }
 
 
-int hidra2::SystemIO::open(const char* __file, int __oflag) {
+int SystemIO::open(const char* __file, int __oflag) {
     return ::open(__file, __oflag);
 }
 
-int hidra2::SystemIO::close(int __fd) {
+int SystemIO::close(int __fd) {
     return ::close(__fd);
 }
 
-ssize_t hidra2::SystemIO::read(int __fd, void* buf, size_t count) {
+ssize_t SystemIO::read(int __fd, void* buf, size_t count) {
     return ::read(__fd, buf, count);
 }
 
-ssize_t hidra2::SystemIO::write(int __fd, const void* __buf, size_t __n) {
+ssize_t SystemIO::write(int __fd, const void* __buf, size_t __n) {
     return ::write(__fd, __buf, __n);
 }
+
+}
\ No newline at end of file
diff --git a/common/cpp/src/system_io_linux.cpp b/common/cpp/src/system_io_linux.cpp
index 290ef2829220ccf83f6f41320d8437a3d45c5614..c4b3a5be8a7e497e0e3132f7cc3da9738b319f33 100644
--- a/common/cpp/src/system_io_linux.cpp
+++ b/common/cpp/src/system_io_linux.cpp
@@ -41,15 +41,7 @@ bool IsDirectory(const struct dirent* entity) {
            strstr(entity->d_name, ".") == nullptr;
 }
 
-system_clock::time_point GetTimePointFromFile(const string& fname, IOErrors* err) {
-
-    struct stat t_stat {};
-    int res = stat(fname.c_str(), &t_stat);
-    if (res < 0) {
-        *err = IOErrorFromErrno();
-        return system_clock::time_point{};
-    }
-
+void SetModifyDate(const struct stat& t_stat, FileInfo* file_info) {
 #ifdef __APPLE__
 #define st_mtim st_mtimespec
 #endif
@@ -59,7 +51,43 @@ system_clock::time_point GetTimePointFromFile(const string& fname, IOErrors* err
 #undef st_mtim
 #endif
 
-    return system_clock::time_point {std::chrono::duration_cast<system_clock::duration>(d)};
+    file_info->modify_date = system_clock::time_point
+    {std::chrono::duration_cast<system_clock::duration>(d)};
+}
+
+void SetFileSize(const struct stat& t_stat, FileInfo* file_info) {
+    file_info->size = t_stat.st_size;
+}
+
+void SetFileName(const string& path, const string& name, FileInfo* file_info) {
+    file_info->relative_path = path;
+    file_info->base_name = name;
+}
+
+struct stat FileStat(const string& fname, IOErrors* err) {
+    struct stat t_stat {};
+    int res = stat(fname.c_str(), &t_stat);
+    if (res < 0) {
+        *err = IOErrorFromErrno();
+    }
+    return t_stat;
+}
+
+FileInfo GetFileInfo(const string& path, const string& name, IOErrors* err) {
+    FileInfo file_info;
+
+    SetFileName(path, name, &file_info);
+
+    auto t_stat = FileStat(path + "/" + name, err);
+    if (*err != IOErrors::NO_ERROR) {
+        return FileInfo{};
+    }
+
+    SetFileSize(t_stat, &file_info);
+
+    SetModifyDate(t_stat, &file_info);
+
+    return file_info;
 }
 
 void ProcessFileEntity(const struct dirent* entity, const std::string& path,
@@ -69,11 +97,8 @@ void ProcessFileEntity(const struct dirent* entity, const std::string& path,
     if (entity->d_type != DT_REG) {
         return;
     }
-    FileInfo file_info;
-    file_info.relative_path = path;
-    file_info.base_name = entity->d_name;
 
-    file_info.modify_date = GetTimePointFromFile(path + "/" + entity->d_name, err);
+    FileInfo file_info = GetFileInfo(path, entity->d_name, err);
     if (*err != IOErrors::NO_ERROR) {
         return;
     }
diff --git a/tests/common/cpp/include/testing.h b/tests/common/cpp/include/testing.h
index c3c24b6b819eac12f0f20b19edc135480bb6fde1..a78cdba7e38e6ade4f3957f371cc359e4566f6b4 100644
--- a/tests/common/cpp/include/testing.h
+++ b/tests/common/cpp/include/testing.h
@@ -6,6 +6,8 @@
 namespace hidra2 {
 
 void M_AssertEq(const std::string& expected, const std::string& got);
+void M_AssertEq(int expected, int got);
+
 
 }
 
diff --git a/tests/common/cpp/src/testing.cpp b/tests/common/cpp/src/testing.cpp
index e9a9adae60a4a3eaf0f512b52442f12fd188bf11..aa92831891e5687e690dacb1067ce96a25b339dc 100644
--- a/tests/common/cpp/src/testing.cpp
+++ b/tests/common/cpp/src/testing.cpp
@@ -4,7 +4,8 @@
 
 namespace hidra2 {
 
-void M_AssertEq(const std::string& expected, const std::string& got) {
+template<typename T>
+void T_AssertEq(const T& expected, const T& got) {
     if (expected != got) {
         std::cerr << "Assert failed:\n"
                   << "Expected:\t'" << expected << "'\n"
@@ -12,5 +13,16 @@ void M_AssertEq(const std::string& expected, const std::string& got) {
         abort();
     }
 }
+
+
+void M_AssertEq(const std::string& expected, const std::string& got) {
+    T_AssertEq(expected, got);
+}
+
+void M_AssertEq(int expected, int got) {
+    T_AssertEq(expected, got);
+}
+
+
 }
 
diff --git a/tests/system_io/read_file_content/CMakeLists.txt b/tests/system_io/read_file_content/CMakeLists.txt
index 7c5c9a53d0c84a457a51d804dff29a9cf2fc8dfe..21ad081c58db0b10f91b9ac7a45f6085802010dc 100644
--- a/tests/system_io/read_file_content/CMakeLists.txt
+++ b/tests/system_io/read_file_content/CMakeLists.txt
@@ -14,7 +14,7 @@ set_target_properties(${TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX)
 ################################
 
 add_test_setup_cleanup(${TARGET_NAME})
-add_integration_test(${TARGET_NAME} readfile "test/1 readerror")
+add_integration_test(${TARGET_NAME} readfile "test/1 123")
 add_integration_test(${TARGET_NAME} filenotfound "test_notexist notfound")
 add_integration_test(${TARGET_NAME} filenoaccess "file_noaccess noaccess")
 
diff --git a/tests/system_io/read_file_content/read_file_content.cpp b/tests/system_io/read_file_content/read_file_content.cpp
index 9e6f6980b3cb9f151a5de34b8444a94f5729eb9b..f6af4619b5f43a185efc2106d5beed66f575d9db 100644
--- a/tests/system_io/read_file_content/read_file_content.cpp
+++ b/tests/system_io/read_file_content/read_file_content.cpp
@@ -1,6 +1,8 @@
 #include <iostream>
 #include <system_wrappers/system_io.h>
 
+#include <memory>
+#include <string>
 #include "testing.h"
 
 using hidra2::SystemIO;
@@ -16,7 +18,7 @@ int main(int argc, char* argv[]) {
 
     IOErrors err;
     auto io = std::unique_ptr<SystemIO> {new SystemIO};
-    auto data = io->GetDataFromFile(argv[1], &err);
+    auto data = io->GetDataFromFile(argv[1], expect.size(), &err);
 
     std::string result;
 
@@ -27,6 +29,7 @@ int main(int argc, char* argv[]) {
     case IOErrors::NO_ERROR:
         for(auto symbol : data)
             result += symbol;
+        M_AssertEq(expect.size(), result.size());
         break;
     case IOErrors::PERMISSIONS_DENIED:
         result = "noaccess";
@@ -41,7 +44,5 @@ int main(int argc, char* argv[]) {
     }
 
     M_AssertEq(expect, result);
-
-
     return 0;
 }
diff --git a/tests/system_io/read_files_in_folder/read_folder_content.cpp b/tests/system_io/read_files_in_folder/read_folder_content.cpp
index bfa8e2d9fa91ddb4f0c14a9818aca21d5523a00c..62d69b20ceedcd59cc8a7329b141f8b7aecf1ae5 100644
--- a/tests/system_io/read_files_in_folder/read_folder_content.cpp
+++ b/tests/system_io/read_files_in_folder/read_folder_content.cpp
@@ -40,6 +40,5 @@ int main(int argc, char* argv[]) {
 
     M_AssertEq(expect, result);
 
-
     return 0;
 }
diff --git a/worker/api/cpp/src/folder_data_broker.cpp b/worker/api/cpp/src/folder_data_broker.cpp
index 41ddb97698549aa6b72411684a78339b0c4e01bb..a9b6ffd93824f88786c14c84578be8730021ff74 100644
--- a/worker/api/cpp/src/folder_data_broker.cpp
+++ b/worker/api/cpp/src/folder_data_broker.cpp
@@ -79,7 +79,7 @@ WorkerErrorCode FolderDataBroker::GetNext(FileInfo* info, FileData* data) {
     IOErrors ioerr;
     *data = io__->GetDataFromFile(base_path_ + "/" + info->relative_path +
                                   (info->relative_path.empty() ? "" : "/") +
-                                  info->base_name, &ioerr);
+                                  info->base_name, info->size, &ioerr);
 
     return MapIOError(ioerr);
 }
diff --git a/worker/api/cpp/unittests/test_folder_broker.cpp b/worker/api/cpp/unittests/test_folder_broker.cpp
index c5e6ce04454a6c9ed68762e2f906fc1b98c0b05d..9060e2c72d7d80e7b1a8544bc295b5f32ddd5863 100644
--- a/worker/api/cpp/unittests/test_folder_broker.cpp
+++ b/worker/api/cpp/unittests/test_folder_broker.cpp
@@ -36,7 +36,7 @@ TEST(FolderDataBroker, SetCorrectIO) {
 
 class FakeIO: public IO {
   public:
-    FileData GetDataFromFile(const std::string& fname, IOErrors* err) {
+    FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err)override {
         *err = IOErrors::NO_ERROR;
         return {};
     };
@@ -58,6 +58,7 @@ class FakeIO: public IO {
         *err = IOErrors::NO_ERROR;
         std::vector<FileInfo> file_infos;
         FileInfo fi;
+        fi.size = 100;
         fi.base_name = "1";
         file_infos.push_back(fi);
         fi.base_name = "2";
@@ -95,7 +96,7 @@ class IOEmptyFodler: public FakeIO {
 
 class IOCannotOpenFile: public FakeIO {
   public:
-    FileData GetDataFromFile(const std::string& fname, IOErrors* err)  {
+    FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err)  {
         *err = IOErrors::PERMISSIONS_DENIED;
         return {};
     };
@@ -168,6 +169,8 @@ TEST_F(FolderDataBrokerTests, GetNextReturnsFileInfo) {
 
     ASSERT_THAT(err, Eq(WorkerErrorCode::OK));
     ASSERT_THAT(fi.base_name, Eq("1"));
+    ASSERT_THAT(fi.size, Eq(100));
+
 }
 
 TEST_F(FolderDataBrokerTests, SecondNextReturnsAnotherFileInfo) {
@@ -201,53 +204,52 @@ TEST_F(FolderDataBrokerTests, GetNextReturnsErrorWhenFilePermissionsDenied) {
     ASSERT_THAT(err, Eq(WorkerErrorCode::PERMISSIONS_DENIED));
 }
 
+
 class OpenFileMock : public FakeIO {
   public:
-    MOCK_METHOD2(GetDataFromFile, FileData(const std::string&, IOErrors*));
+    MOCK_METHOD3(GetDataFromFile, FileData(const std::string&, uint64_t, IOErrors*));
 };
 
-TEST_F(FolderDataBrokerTests, GetNextCallsGetDataFileWithFileName) {
+
+class GetDataFromFileTests : public Test {
+  public:
+    std::unique_ptr<FolderDataBroker> data_broker;
     OpenFileMock mock;
-    data_broker->io__.reset(&mock);
-    data_broker->Connect();
     FileInfo fi;
     FileData data;
+    void SetUp() override {
+        data_broker = std::unique_ptr<FolderDataBroker> {new FolderDataBroker("/path/to/file")};
+        data_broker->io__ = std::unique_ptr<IO> {&mock};
+        data_broker->Connect();
+    }
+    void TearDown() override {
+        data_broker->io__.release();
+    }
+};
+
+TEST_F(GetDataFromFileTests, GetNextCallsGetDataFileWithFileName) {
+    EXPECT_CALL(mock, GetDataFromFile("/path/to/file/1", _, _)).
+    WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::NO_ERROR), testing::Return(FileData{})));
 
-    auto err = IOErrors::NO_ERROR;
-    EXPECT_CALL(mock, GetDataFromFile("/path/to/file/1", _)).
-    WillOnce(DoAll(testing::SetArgPointee<1>(IOErrors::NO_ERROR), testing::Return(FileData{})));
     data_broker->GetNext(&fi, &data);
-    data_broker->io__.release();
 }
 
 
-TEST_F(FolderDataBrokerTests, GetNextReturnsData) {
-    OpenFileMock mock;
-    data_broker->io__.reset(&mock);
-    data_broker->Connect();
-    FileInfo fi;
-    FileData data;
+TEST_F(GetDataFromFileTests, GetNextReturnsData) {
+    EXPECT_CALL(mock, GetDataFromFile(_, _, _)).
+    WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::NO_ERROR), testing::Return(FileData{'1'})));
 
-    EXPECT_CALL(mock, GetDataFromFile(_, _)).
-    WillOnce(DoAll(testing::SetArgPointee<1>(IOErrors::NO_ERROR), testing::Return(FileData{'1'})));
     data_broker->GetNext(&fi, &data);
-    data_broker->io__.release();
 
     ASSERT_THAT(data[0], Eq('1'));
 }
 
 
-TEST_F(FolderDataBrokerTests, GetNextReturnsErrorWhenCannotReadData) {
-    OpenFileMock mock;
-    data_broker->io__.reset(&mock);
-    data_broker->Connect();
-    FileInfo fi;
-    FileData data;
+TEST_F(GetDataFromFileTests, GetNextReturnsErrorWhenCannotReadData) {
+    EXPECT_CALL(mock, GetDataFromFile(_, _, _)).
+    WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::READ_ERROR), testing::Return(FileData{})));
 
-    EXPECT_CALL(mock, GetDataFromFile(_, _)).
-    WillOnce(DoAll(testing::SetArgPointee<1>(IOErrors::READ_ERROR), testing::Return(FileData{})));
     auto err = data_broker->GetNext(&fi, &data);
-    data_broker->io__.release();
 
     ASSERT_THAT(err, Eq(WorkerErrorCode::ERROR_READING_FROM_SOURCE));
     ASSERT_TRUE(data.empty());